测试类:
package source.day2;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
/**
* spring集合了多种初始化方法(BeanPostProcessor是初始其他类用的)的类
*
*/
public class MoreInitBeanFactyPostProcess implements BeanFactoryAware,BeanNameAware,InitializingBean
,BeanPostProcessor,BeanFactoryPostProcessor{
public MoreInitBeanFactyPostProcess(){
System.out.println("构造函数执行了!");
}
/**
* BeanFactoryAware初始化
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryAware的初始方法执行了:"+beanFactory.getClass().getName());
}
/**
* BeanNameAware初始化
*/
@Override
public void setBeanName(String name) {
System.out.println("BeanNameAware初始化,它的name值是 "+name);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean接口的初始化的afterPropertiesSet()执行了!");
}
/***有其他bean初始化的的时候用,用来给实例化的bean进行修改,在spring框架内部用的很频繁
详见springMvc中的ServletContextAware就是利用这个实现的。
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (getServletContext() != null && bean instanceof ServletContextAware) {
((ServletContextAware) bean).setServletContext(getServletContext());
}
if (getServletConfig() != null && bean instanceof ServletConfigAware) {
((ServletConfigAware) bean).setServletConfig(getServletConfig());
}
return bean;
}
**/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor的postProcessBeforeInitialization执行了");
return bean;
}
/**有其他bean初始化的时候调用**/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor的postProcessAfterInitialization执行了");
return bean;
}
/**可以更改beanFactory内定义的beandefineds,肯定要在此类实例化和各种初始化完成,就马上去干这个活!
* -----------其他的bean实例化和初始化跟此方法无关。它改的是beanFactory内bean的原生形态beanDefined。
***/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryPostProcessor的postProcessBeanFactory执行了");
}
public void initMethd(){
System.out.println("bean的配置属性initMethd配置的方法执行了");
}
public void begin(){
System.out.println("正常方法调用");
}
}
测试调用:
public class Test_2 {
@Test
public void test2(){
String xmlPath = "source/day2/beans.xml"; //可使用通配符 source/day1/*.xml
@SuppressWarnings("resource")
ApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
MoreInitBeanFactyPostProcess bean = (MoreInitBeanFactyPostProcess) context.getBean("moreBean");
bean.begin();
}
}
测试打印结果:
构造函数执行了!BeanNameAware初始化,它的name值是 moreBean
BeanFactoryAware的初始方法执行了:org.springframework.beans.factory.support.DefaultListableBeanFactory
InitializingBean接口的初始化的afterPropertiesSet()执行了!
bean的配置属性initMethd配置的方法执行了
BeanFactoryPostProcessor的postProcessBeanFactory执行了
正常方法调用
二、流程总结:
2.1 首先是实例化本类前补充-->判断有没有依赖注入的其他类,先实例化其他类,再实例化本类。
2.2 本类实例化
2.3 本类注入的类,通过setXX方法,填充属性。
2.4 Aware方法(先BeanNameAware,再BeanFactoryAware)
2.5 BeanPostProcess的postProcessBeforeInitialization()起作用了(备注:此类的容器没有其他类执行此操作,所以没打印)
2.6 InitializingBean接口的初始方法afterPropertiesSet()执行。
2.7 Bean配置属性的initMethod配置的方法initMethod执行了//或者注解@PostConstruct
2.8 BeanPostProcess的另外一个方法(备注:同2.5)
2.9 这个时候bean就准备好了,可以正常方法调用了,但是这个类实现了BeanFactoryPostProcess,这个方法会再所有的初始化方法都执行完成时(或者说因为要完成本类的这个职责,先要把此类new出来进行各种初始化才可以用),需要执行postProcessBeanFactory对容器中的beanDefineds进行修改。再执行正常的调用!
以上流程说的都是单例模式的,会在容器初始化的时候就完成以上的初始化。如果是多例模式。(多点好奇心:假如此类还有这些特殊操作,即实现了BeanFactoryProcess,那么会出现一个诡异的现象。此类会实例化3次,但是呢,具体职责的方法只会执行一次,而且后2次的实例还受到了第一次实例的BeanPostProcessor的postProcessAfterInitialization执行了,详见把demo的bean配置改成scope = prototype),那么类的实例化和初始化会推迟到getBean时执行,但是它所依赖的bean,会递归调用它依赖类的此一系列的操作(详见源码的getBean()方法),也分为单例和多例,不同的模式,有不同的策略,和此类一样。
附件: