Spring Bean加载过程(二)
来源:互联网 发布:linux误删除文件恢复 编辑:程序博客网 时间:2024/06/17 15:07
在前面 Spring Bean加载过程 文章中,分析了在refresh()
方法中obtainFreshBeanFactory()
执行完后所有的BeanDefinition已经初始化好了。
之后会调用所有注册的BeanFactoryPostProcessor
的Bean:
invokeBeanFactoryPostProcessors(beanFactory);
在方法里会从beanFactory中获取实现了BeanFactoryPostProcessor
的BeanDefinition,并从beanFactory中getBean()
来取得该bean,并调用其实现的postProcessBeanFactory()
方法。
先来看下getBean()
方法,我们知道BeanFactory接口中定义了几个getBean方法,就是向IoC容器索取管理的Bean的方法,在getBean时会完成对应bean的初始化。由于调用的层次比较复杂,最终调用了AbstractBeanFactory#getBean()
方法,该方法实际上是调用了其AbstractBeanFactory#doGetBean()
方法。
在doGetBean()
方法中,如果Bean定义的单态模式(Singleton),则容器在创建之前先从缓存中查找,以确保整个容器中只存在一个实例对象。如果Bean定义的是原型模式(Prototype),则容器每次都会创建一个新的实例对象。除此之外,Bean定义还可以扩展为指定其生命周期范围。具体的Bean实例对象的创建过程由createBean()
方法完成,其具体的实现类是AbstractAutowireCapableBeanFactory
,最终的bean的创建是AbstractAutowireCapableBeanFactory#doCreateBean
:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); //...... // Initialize the bean instance. Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { exposedObject = initializeBean(beanName, exposedObject, mbd); } } //...... return exposedObject; }
createBeanInstance()
方法是根据XML的定义调用bean的有参或无参构造函数。跟踪该方法,我们最终会发现有个getInstantiationStrategy()方法,该方法的作用是获得实例化的策略对象,也就是指通过哪种方案进行实例化的过程,Spring当中提供了两种实例化方案:BeanUtils和CGLIB方式。BeanUtils实现机制是通过Java的反射机制,Cglib是一个第三方类库采用的是一种字节码加强方式机制。 populateBean()
方法会获得BeanDefinition中设置的property信息,对这些property进行赋值,即依赖注入的过程。在这个方法里完成对属性的注入,比如setXxx()方法的调用、属性的注解注入。
对于initializeBean()
方法:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { invokeAwareMethods(beanName, bean); return null; } }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { 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()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
invokeAwareMethods()
方法判断是BeanNameAware、BeanFactoryAware之类的Aware类型,如果是的话就执行对应方法。 applyBeanPostProcessorsBeforeInitialization()
方法是如果实现了BeanPostProcessor接口,这里会执行postProcessBeforeInitialization方法。 invokeInitMethods()
方法中,先判断是否实现了InitializingBean接口,如果是执行afterPropertiesSet()方法,然后如果配置了init-method就执行initMethod方法。 applyBeanPostProcessorsAfterInitialization()
方法是如果实现了BeanPostProcessor接口,这里会执行postProcessAfterInitialization方法。
到此为止一个BeanFactoryPostProcessor的Bean就初始化完成了。
于是就可以通过BeanFactoryPostProcessor的postProcessBeanFactory()
的调用,来修改某些beanDefinition的值,示例:
@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { String[] beanNames = beanFactory.getBeanDefinitionNames(); for (String beanName : beanNames) { BeanDefinition bd = beanFactory.getBeanDefinition(beanName); System.out.println(bd.getBeanClassName()); PropertyValue[] pvArray = bd.getPropertyValues().getPropertyValues(); for (PropertyValue pv : pvArray) { System.out.println(pv.getName() + "---" + pv.getValue()); } ConstructorArgumentValues cas = bd.getConstructorArgumentValues(); for (ConstructorArgumentValues.ValueHolder valueHolder : cas.getIndexedArgumentValues().values()) { System.out.println(valueHolder.getName() + "---" + valueHolder.getValue()); } for (ConstructorArgumentValues.ValueHolder valueHolder : cas.getGenericArgumentValues()) { System.out.println(valueHolder.getName() + "---" + valueHolder.getValue()); } } }
Spring中的PropertyPlaceholderConfigurer
正是通过这种方式来实现了配置宏替换。
- 需要注意的是,BeanPostProcessor在源码注释已经表述了,只有当其它非实现BeanPostProcessor的bean且在同一个容器的bean在初始化的时候,才会回调BeanPostProcessor重写的那些方法,所以一个继承了BeanPostProcessor的类初始化会发现是不会有override方法的回调的。
补充:
实例化Bean的过程中有以下几个节点:
1)构造函数调用、设置属性值;
2)调用Bean中的BeanNameAware.setBeanName()方法,如果该Bean实现了BeanNameAware接口;
3)调用Bean中的BeanFactoryAware.setBeanFactory()方法,如果该Bean实现了BeanFactoryAware接口;
4)调用BeanPostProcessors.postProcessBeforeInitialization()方法;
5)调用Bean中的afterPropertiesSet方法,如果该Bean实现了InitializingBean接口;
6)调用Bean中的init-method,通常是在配置bean的时候指定了init-method,例如:<bean class="beanClass"init-method="init"></bean>
7)调用BeanPostProcessors.postProcessAfterInitialization()方法;
8)如果该Bean是单例的,则当容器销毁并且该Bean实现了DisposableBean接口的时候,调用destory方法;如果该Bean是prototype,则将准备好的Bean提交给调用者,后续不再管理该Bean的生命周期。
执行顺序:Constructor > @PostConstruct > InitializingBean > init-method
,@PostConstruct优先于后者是因为CommonAnnotationBeanPostProcessor
这个类,它继承自InitDestroyAnnotationBeanPostProcessor
,用于处理@PostConstruct这类注解的BeanPostProcessor,所以先于InitializingBean执行。
- Spring Bean加载过程(二)
- spring bean加载过程
- Spring Bean加载过程
- spring bean的加载过程
- Spring bean的加载过程
- spring加载bean的过程
- 【spring源码分析】加载bean过程(1)
- 【spring源码分析】加载bean过程(2)
- spring源码阅读之Bean的加载(二)
- SPRING 启动加载BEAN 的代码过程
- Spring中bean的加载过程
- spring源码分析 加载bean过程
- Spring bean 标签加载、解析过程分析
- Spring bean 标签加载、解析过程分析
- Spring Bean加载(一)
- Spring(二)--Bean装配
- Spring之Bean(二)
- Spring Bean载入(二)
- windows cmd命令显示UTF8设置
- 内存申请过程
- go lang学习笔记(1)
- 在Android设备上配置TensorFlow(三)解读ClassifierActivity源代码
- 1.排序之冒泡排序
- Spring Bean加载过程(二)
- Bean 类 id name&& bean的属性和合作者(声明与使用)
- leetcode 520. Detect Capital(C语言)
- 两种for循环的实质
- pom.xml/Maven
- 两个线程进行数据交换的Exchanger
- 关于xampp的默认目录 以及 修改问题
- 侧滑
- Mysql中的左连接、右连接的姿势