spring各种初始化方法大乱斗

测试类:

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()方法),也分为单例和多例,不同的模式,有不同的策略,和此类一样。

附件:

    

猜你喜欢

转载自blog.csdn.net/shuixiou1/article/details/79682954
今日推荐