乐趣区

关于后端:详解-Spring-中-Bean-的生命周期

世事洞明皆学识,人情练达即文章。

这一节筹备给大家解说 Spring 容器中的 Bean 的生命周期。这一节我集体感觉还是比拟实用的,在理论工作当中常常会用到这些常识来解决一些十分辣手的问题。

ApplicationContext 中 Bean 的生命周期

先来张图:

大家看到这张图必定是一脸懵逼。不要焦急,我来缓缓解释: 从 getBean(…)为触发点,Spring 容器的 Bean 生命周期就经验了图中的生命周期,先分个类:

  • 图中绿色箭头的三个步骤 (InstantiationAwareBeanPostProcessor) 和粉红色箭头的两个步骤 (BeanPostProcessor) 为容器级的生命周期接口, 当 Spring 每加载任何一个 Bean 到容器中时,这些接口都会起到如图中的几次调用。这两个处理器叫做 ” 容器级后处理器 ”, 他们的影响是全局的,可能影响所有的 Bean.
  • 图中大红色圆圈圈住的接口叫做 ” 工厂级后处理器 ”, 相似的接口还有 CustomEditorConfigurer,PropertyPlaceholderConfigurer 等,这类接口只在上下文初始化的时候调用一次,其目标是实现一些配置文件的加工解决工作。
  • 剩下的就简略了,属于 Bean 级别的接口,专属于某个 Bean 所有,每个 Bean 实例化的时候调用本人特有的。

值得一提的是,无论是 ” 容器级后处理器 ” 还是 ” 工厂级后处理器 ”,他们都是能够配置多个的(如,配置两个 BeanPostProcessor),如果想管制他们的调用程序,实现一个 org.springframework.core.Ordered 接口即可。当然了,个别不必,个别一类后处理器只有一个即可。

重点强调!:

这些接口的调用程序并不是一尘不变的,会轻易 Spring 的版本变动而变动,大家要做的是万变不离其宗,晓得可能通过这些接口在 Bean 初始化的时做一些属性上的操作。调用程序要依据具体的版本来本人测试。上面我会给大家来列一个例子:

public class Student implements BeanFactoryAware, BeanNameAware,
        InitializingBean, DisposableBean,ApplicationContextAware {
    private String name;

    public Student(String name) {this.name = name;}

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("BeanFactoryAware......");
    }

    @Override
    public void setBeanName(String s) {System.out.println("BeanNameAware......");
    }

    @Override
    public void destroy() throws Exception {System.out.println("DisposableBean......");
    }

    @Override
    public void afterPropertiesSet() throws Exception {System.out.println("InitializingBean......");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("ApplicationContextAware......");
    }
}

BeanFactoryPostProcessor:

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {public MyBeanFactoryPostProcessor() {super();
        System.out.println("这是 BeanFactoryPostProcessor 实现类结构器!!");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
            throws BeansException {System.out.println("BeanFactoryPostProcessor 调用 postProcessBeanFactory 办法");
        BeanDefinition bd = arg0.getBeanDefinition("student");
        MutablePropertyValues propertyValues = bd.getPropertyValues();
        // 配置文件中的信息在加载到 Spring 中后以 BeanDefinition 的模式存在. 在这里又能够更改 BeanDefinition, 所以能够了解为更改配置文件外面的内容
//        propertyValues.add("zdy","123");
    }

}

BeanPostProcessor:

public class MyBeanPostProcessor implements BeanPostProcessor {public MyBeanPostProcessor() {super();
        System.out.println("这是 BeanPostProcessor 实现类结构器!!");
    }

    @Override
    public Object postProcessAfterInitialization(Object arg0, String arg1)
            throws BeansException {System.out.println("BeanPostProcessor 接口办法 After 对属性进行更改!");
        return arg0;
    }

    @Override
    public Object postProcessBeforeInitialization(Object arg0, String arg1)
            throws BeansException {System.out.println("BeanPostProcessor 接口办法 Before 对属性进行更改!");
        return arg0;
    }
}

InstantiationAwareBeanPostProcessorAdapter:

public class MyInstantiationAwareBeanPostProcessor extends
        InstantiationAwareBeanPostProcessorAdapter {public MyInstantiationAwareBeanPostProcessor() {super();
        System.out.println("这是 InstantiationAwareBeanPostProcessorAdapter 实现类结构器!!");
    }

    // 接口办法、实例化 Bean 之前调用
    @Override
    public Object postProcessBeforeInstantiation(Class beanClass,
                                                 String beanName) throws BeansException {System.out.println("InstantiationAwareBeanPostProcessor 调用 Before 办法");
        return null;
    }

    // 接口办法、实例化 Bean 之后调用
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {System.out.println("InstantiationAwareBeanPostProcessor 调用 Ater 办法");
        return bean;
    }

    // 接口办法、设置某个属性时调用
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs,
                                                    PropertyDescriptor[] pds, Object bean, String beanName)
            throws BeansException {System.out.println("InstantiationAwareBeanPostProcessor 调用 postProcessPropertyValues 办法");
        return pvs;
    }
}

而后咱们的 Main 办法:

public class App {public static void main(String[] args) {ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student stu = (Student) ac.getBean("student");
        stu.setName("wangwu");
    }
}

Spring 文件最简略:(留神要把咱们本人定义的处理器全副加到容器里去)

<?xml version="1.0" encoding="UTF-8"?>
        <beans
        <bean id="student" class="com.zdy.Student">
<constructor-arg value="zhangsan"/>
</bean>
    <bean id="myBeanFactoryPostProcessor" class="com.zdy.MyBeanFactoryPostProcessor"></bean>
<bean id="myInstantiationAwareBeanPostProcessor" class="com.zdy.MyInstantiationAwareBeanPostProcessor"></bean>
    <bean id="myBeanPostProcessor" class="com.zdy.MyBeanPostProcessor"></bean>
</beans>

而后 run 一下子,看后果:

这是 BeanFactoryPostProcessor 实现类结构器!!BeanFactoryPostProcessor 调用 postProcessBeanFactory 办法
这是 InstantiationAwareBeanPostProcessorAdapter 实现类结构器!!这是 BeanPostProcessor 实现类结构器!!InstantiationAwareBeanPostProcessor 调用 Before 办法
InstantiationAwareBeanPostProcessor 调用 postProcessPropertyValues 办法
BeanNameAware......
BeanFactoryAware......
ApplicationContextAware......
BeanPostProcessor 接口办法 Before 对属性进行更改!InitializingBean......
InstantiationAwareBeanPostProcessor 调用 Ater 办法
BeanPostProcessor 接口办法 After 对属性进行更改!

好了,其实大抵流程就说完了,我大抵针对 Bean 的生命周期说一下:Spring 为了尽可能的把本人外部的货色机制裸露进去给用户应用,所以在 Bean 创立的过程中加了很多机制,通过所谓的 ” 处理器 ”Processor 裸露进去, 而后处理器都有本人的程序,咱们须要做的就是定义好处理器的逻辑,而后注册到 Sprinhg 容器中,Spring 就会调用了。

其次,还有一种形式,就是让咱们的 Bean 实现一些接口(相似于 ApplicationContextAware),通过这种形式,在 Bean 初始化的某个步骤调用接口定义好的办法来传入一些信息进来,像 ApplicationContextAware 就把 ApplicationContext 给传给咱们了。

而后我给大家说几个实用点的知识点,大家记着,用到时回来翻一翻就能够了:

  1. 下面的生命周期流程图,时候的时候留神调用先后顺序,防止属性被笼罩的景象。
  2. BeanFactoryPostProcessor 次要是在 Spring 刚加载完配置文件,还没来得及初始化 Bean 的时候做一些操作。比方篡改某个 Bean 在配置文件中配置的内容。
  3. InstantiationAwareBeanPostProcessorAdapter 根本没什么鸟用,Bean 初始化后,还没有设置属性值时调用,和 BeanFactoryPostProcessor 一样,能够篡改配置文件加载到内存中的信息。
  4. ApplicationContextAware: 用途很大,注入了 ApplicationContext 到 Bean 中。
  5. InitializingBean: 有用途,能够在 Bean 属性全副改完之后,再做一些定制化操作。
  6. BeanPostProcessor:没什么用,Spring 框架外部应用的比拟猛,像什么 AOP,动静代理,都是在这搞事。前期有工夫和大家剖析。
  7. 其余的像什么 init-method,destroy 办法,根本都是个陈设。。我是没怎么用过,只晓得有这么回事。

结语

好了,Bean 的生命周期算上和大家分享完了,其实没什么货色,大家晓得有这么回事,能用到 ” 后处理器 ” 搞事的时候回来大抵看下程序即可。其次就是一些 Bean 实现的接口,最罕用的就是 (ApplicationContextAware 和 InitializingBean) 了。还有就是 BeanPostProcessor,因为这个接口的办法里会把 Bean 实体以 Object 传进去,所以能够进行一些属性上的操作。

退出移动版