1  实例化过程与生命周期

如下图:

springboot bean实例化后修改属性 spring实例化bean的过程_spring

Bean实例(单例bean)生命周期的执行过程如下:

  1. Spring对bean进行实例化,默认bean是单例;
  2. Spring对bean进行依赖注入
  3. 如果bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法;
  4. 如果bean实现了BeanFactoryAware接口,spring将调用setBeanFactory方法,将BeanFactory实例传进来;
  5. 如果bean实现了ApplicationContextAware接口,它的setApplicationContext()方法将被调用,将应用上下文的引用传入到bean中;
  6. 如果bean实现了BeanPostProcessor接口,它的postProcessBeforeInitialization方法将被调用;
  7. 如果bean实现了InitializingBean接口,spring将调用它的afterPropertiesSet接口方法,类似的如果bean使用了init-method属性声明了初始化方法,则再调用该方法;
  8. 如果bean实现了BeanPostProcessor接口,它的postProcessAfterInitialization接口方法将被调用;
  9. 此时bean已经准备就绪,可以被应用程序使用了,他们将一直驻留在应用上下文中,直到该应用上下文被销毁;
  10. 若bean实现了DisposableBean接口,spring将调用它的distroy()接口方法。如果bean使用了destroy-method属性声明了销毁方法,则再调用该方法;

 

2 测试BeanPostProcessor接口,InitializingBean接口,DisposableBean接口

我们首先测试一下bean在进行实例化与依赖注入之后,要进行初始化操作的前后一些操作,即测试一下测试BeanPostProcessor接口,InitializingBean接口,DisposableBean接口

测试类如下:

public class Car implements InitializingBean,DisposableBean {

    public Car(){
        System.out.println("构造器...");
    }
    //配置文件中的属性init-method指定的方法
    public void initMethod(){
        System.out.println("属性init-method方法...");
    }
    //配置文件中的属性destroy-method指定的方法
    public void destryMethod(){
        System.out.println("属性destroy-method方法...");
    }
    public void drive(){
        System.out.println("开车...");
    }
    //InitializingBean接口的方法
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean的afterPropertiesSet()方法...");
    }
    //DisposableBean接口的方法
    public void destroy() throws Exception {
        System.out.println("DisposableBean接口的destroy()方法...");
    }

}

实现BeanPostProcessor接口的类如下:

public class MyPostProcessor implements BeanPostProcessor {


    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化前的操作postProcessBeforeInitialization...");
        return bean;//返回该bean,因为拿出来处理之后要放回Ioc容器
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("初始化后的操作postProcessAfterInitialization...");
        return bean;
    }
}

在Xml文件中配置测试类Car和BeanPostProcessor的实现类

<bean id="car" class="Car" init-method="initMethod" destroy-method="destryMethod"/>

    <bean class="MyPostProcessor"/>

测试代码:

public class APP {
    public static void main(String args[]) {
        ClassPathXmlApplicationContext contex=new ClassPathXmlApplicationContext("applicationContext.xml");
        Car car = (Car)contex.getBean("car");
        car.drive();
        contex.close();//关闭应用上下文,则会调用销毁bean的方法
    }
}

测试结果:

springboot bean实例化后修改属性 spring实例化bean的过程_spring_02

2 Aware接口:BeanNameAware、BeanFactoryAware、ApplicationContextAware

Aware的含义是感应,Spring容器的IoC中,所有的bean对于spring容器是无意识的,完全可以把spring容器替换成其他的容器而不需要改变你的代码。

如果需要bean对spring有意识,即知道自己在配置中的id是什么,自己是Beanfactory是什么,自己的ApplicationContext是哪个

则需要用到Aware接口。

xxxAware接口只有一个setXxx()的方法,用于设置Bean的属性

实现这些 Aware接口的Bean在被实例化 之后,可以取得一些相对应的资源,在bean中自动注入对应的属性

例如实现BeanFactoryAware的Bean在实例化后,Spring容器将会注入BeanFactory的实例,而实现ApplicationContextAware的Bean,在Bean被实例化后,将会被注入 ApplicationContext的实例等等。
 

写一个测试类实现这三个接口:

public class MyBean implements BeanNameAware,BeanFactoryAware,ApplicationContextAware{
    private String beanName;
    private BeanFactory beanFactory;
    private ApplicationContext applicationContext;
    //BeanNameAware接口的方法
    public void setBeanName(String beanName) {
        this.beanName=beanName;
    }
    //BeanFactoryAware接口的方法
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory=beanFactory;
    }
    //ApplicationContextAware接口的方法
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext=applicationContext;
    }
    //用于之后测试打印属性的值
    public void print() {
        System.out.println("beanName=" + beanName);
        System.out.println("beanFactory=" + beanFactory);
        System.out.println("applicationContext=" + applicationContext);
    }
}

配置:

<bean id="myBean" class="MyBean"/>

测试代码:

public class APP {
    public static void main(String args[]) {
        ClassPathXmlApplicationContext contex=new ClassPathXmlApplicationContext("applicationContext.xml");
        MyBean myBean = (MyBean)contex.getBean("myBean");
        myBean.print();
    }
}

结果:

beanName=myBean
beanFactory=org.springframework.beans.factory.support.DefaultListableBeanFactory@49e4cb85: defining beans [myBean]; root of factory hierarchy
applicationContext=org.springframework.context.support.ClassPathXmlApplicationContext@b81eda8: startup date [Thu Jan 31 11:25:58 CST 2019]; root of context hierarchy

从结果可知,容器自动给myban注入了属性,beanName是配置文件中的id,beanFactory是spirng默认的DefaultListableBeanFactory类的一个实例,applicationContext是测试代码中创建的ClassPathXmlApplicationContext的一个实例