Spring容器之ClassPathXmlApplicationContext

本文参考了
https://javadoop.com/post/spring-ioc

该文是基于Spring 4.3.9.release版本展开的

对于Java开发者来说,Spring绝对不会陌生,那么其中Spring容器的初始化过程是怎样的呢?该文简要跟踪了ClassPathXmlApplicationContext初始化的过程,现与大家分享。

首先给个ClassPathXmlApplicationContext使用的小例子,直观感受一下。

定义如下测试Bean:

public class TestBean implements InitializingBean, DisposableBean, BeanNameAware, BeanFactoryAware{
    /**
     * @Value和@Autoware是由AutowiredAnnotationBeanPostProcessor处理的;
     * 如果程序中不引入AutowiredAnnotationBeanPostProcessor,则无法解析
     * */
    //在properties文件中配置了username=test
    @Value("${username}")
    private String userName;

    private Integer age;

    public void setUserName(String userName){
        System.out.println("set 方法被调用.....");
        this.userName = userName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getUserName(){
        return this.userName;
    }

    public TestBean(){
        System.out.println("Constructor : 构造器被调用..... | username: "+userName+" | age: "+age);
    }

    public void init(){
        System.out.println("XML : xml文件中init-method指定的方法init被调用..... | username: "+userName+" | age: "+age);
    }

    public void destroyInXml(){
        System.out.println("XML : xml文件中destory-method指定的方法destory被调用..... | username: "+userName+" | age: "+age);

    }
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("Aware : BeanFactoryAware.setBeanFactory被调用..... | username: "+userName+" | age: "+age);
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("Aware : BeanNameAware.setBeanName被调用..... | username: "+userName+" | age: "+age);
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean : destroy()被调用..... | username: "+userName+" | age: "+age);

    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean : afterPropertiesSet()被调用..... | username: "+userName+" | age: "+age);
    }

    /**
     * 默认情况下,Spring不认识@PostConstruct和@PreDestroy注解。
     * 要启用这两个注解,要么注册CommonAnnotationBeanPostProcessor,要么添加配置
     * */
    @PostConstruct
    public void postConstruct(){
        System.out.println("@PostConstruct : 被调用..... | username: "+userName+" | age: "+age);
    }

    @PreDestroy
    public void preDestroy(){
        System.out.println("@PreDestroy : 被调用..... | username: "+userName+" | age: "+age);

    }

    public String toString(){
        System.out.println(this);
        System.out.println("toString()..... | userName : "+userName+" | age: "+age);
        return "";
    }
}

bean的配置如下:


    
    
    
    
    
    

    
        
    

自定义的三个后处理器

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        BeanDefinition testBean = beanFactory.getBeanDefinition("testBean");
        System.out.println("BeanFactoryPostProcessor : postProcessBeanFactory被调用.....");
    }
}
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof TestBean)
            System.out.println("BeanPostProcessor : postProcessBeforeInitialization被调用.....| username : "+((TestBean) bean).getUserName()+" | age: "+((TestBean) bean).getAge());
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof TestBean)
            System.out.println("BeanPostProcessor : postProcessAfterInitialization被调用..... | username : "+((TestBean) bean).getUserName()+" | age: "+((TestBean) bean).getAge());
        return bean;
    }
}
public class MyInstantiationPostProcessor extends AutowiredAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
        if (beanName.equals("testBean"))
            System.out.println("InstantiationAwareBeanPostProcessor : postProcessBeforeInstantiation.....");

        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("testBean"))
            System.out.println("InstantiationAwareBeanPostProcessor : postProcessAfterInstantiation.....| username : "+((TestBean) bean).getUserName() +" | age: "+((TestBean) bean).getAge());

        return true;
    }

    @Override
    public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
            throws BeansException {
        if (bean instanceof TestBean)
            System.out.println("InstantiationAwareBeanPostProcessor : postProcessPropertyValues.....| username : "+((TestBean) bean).getUserName() +" | age: "+((TestBean) bean).getAge());

        return pvs;
    }
}

启动Spring容器:

public class Main {
    public static void main(String[] args){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath*:bean.xml");
        TestBean testBean = (TestBean) context.getBean("testBean");
        //context.getBeanFactory().destroySingletons();
    }
}

运行结果如下:
BeanFactoryPostProcessor : postProcessBeanFactory被调用.....
InstantiationAwareBeanPostProcessor : postProcessBeforeInstantiation.....
Constructor : 构造器被调用..... | username: null | age: null
InstantiationAwareBeanPostProcessor : postProcessAfterInstantiation.....| username : null | age: null
InstantiationAwareBeanPostProcessor : postProcessPropertyValues.....| username : test | age: null
Aware : BeanNameAware.setBeanName被调用..... | username: test | age: 20
Aware : BeanFactoryAware.setBeanFactory被调用..... | username: test | age: 20
BeanPostProcessor : postProcessBeforeInitialization被调用.....| username : test | age: 20
@PostConstruct : 被调用..... | username: test | age: 20
InitializingBean : afterPropertiesSet()被调用..... | username: test | age: 20
XML : xml文件中init-method指定的方法init被调用..... | username: test | age: 20
BeanPostProcessor : postProcessAfterInitialization被调用..... | username : test | age: 20

Bean的初始化过程会调用很多PostProcessor,那么顺序是怎样的呢?我们从ClassPathXmlApplicationContext的启动过程分析一下。


Spring容器之ClassPathXmlApplicationContext_第1张图片
ClassPathXmlApplicationContext-StartUp.png

从上图可看出,ClassPathXmlApplicationContext的启动过程中,有两个步骤是比较重要的,obtainFreshBeanFactory()和finishBeanFactoryInitialization();前一个方法负责读取xml文件,并将这些信息转化为BeanDefinition保存在BeanFactory的map中,后一个方法负责创建(Instantiation)并初始化(Initialization)bean。

在此,简要分析一下后一个方法的主要部分。该方法最后会进入到AbstractAutowireCapableBeanFactorydoCreateBean()中。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
            throws BeanCreationException {

        // 省略不重要的代码
        if (instanceWrapper == null) {
            //运用反射创建bean,此时bean中的属性都没有赋值
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }

        ......
              
        try {
            //调用一些PostProcessor方法
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                 //属性赋值
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
        }

        ......

        // Register bean as disposable.
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        ......

        return exposedObject;
    }
    protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
        PropertyValues pvs = mbd.getPropertyValues();
        ......

        // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
        // state of the bean before properties are set. This can be used, for example,
        // to support styles of field injection.
        boolean continueWithPropertyPopulation = true;

        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        //子类覆写该方法时,不要返回false,否则代码就会跳出
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }

        if (!continueWithPropertyPopulation) {
            return;
        }
        ......

        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

        if (hasInstAwareBpps || needsDepCheck) {
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        //这里会使用AutowiredAnnotationBeanPostProcessor对@Autowire和@Value修饰的属性赋值
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }
        //最后对一般的属性赋值,赋值时又涉及到字段类型的转换问题,后续再分析
        applyPropertyValues(beanName, mbd, bw, pvs);
    }

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction() {
                @Override
                public Object run() {
                    //调用Aware类的方法,比如BeanNameAware
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            //调用Aware类的方法,比如BeanNameAware
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            //调用BeanPostProcessor的postProcessBeforeInitialization()
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            //调用afterPropertiesSet()和init-method方法
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            //调用BeanPostProcessor的postProcessAfterInitialization()
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }
 
 

从上述代码的分析过程,就可以看出前面例子的结果的顺序为何是这样。

补充几点说明:

  • BeanPostProcessorpostProcessBeforeInitialization()的调用时机是在bean的所有属性赋值之后,而不是之前。这里的before Initialization强调的是init-method这些方法之前;
  • @Value和@Autowire修饰的属性的赋值要在普通属性之前;
  • Spring中的注释都是由BeanPostProcessor处理的,比如@Autowire由AutowiredAnnotationBeanPostProcessor处理,@Required由RequiredAnnotationBeanPostProcessor处理,Java自带的@PostConstruct等由CommonAnnotationBeanPostProcessor处理,这些Processor可以由一键引入,又由ContextNamespaceHandler解析。

你可能感兴趣的:(Spring容器之ClassPathXmlApplicationContext)