如果用了Spring框架几年,只听说过IOC,不知道IOC核心实现的伙伴们来看一下本篇文章。
Spring框架作为Java王国的地基,我觉得它包含了很多精妙的设计,例如Bean工厂设计、Bean的生命周期、tx、aop、web、mvc等,最核心基本的Bean设计是Spring 的框架的灵魂,本文就Bean的生命周期全流程做源码程度上的解析,欢迎各位大佬指点江山。
Bean的生命周期贯彻整个IOC的流程,那么Spring是如何实现IOC的?先上一张DefaultListableBeanFactory的UML图来来感受Spring IOC设计的强大,跟着DefaultListableBeanFactory去揭开Spring框架的核心面纱, 大家可以根据需要自取下图。
DefaultListableBeanFactory掌管了Bean生命周期的大权,Bean的创建、初始化、销毁,添加BeanPostProcessor等功能,可以说是Spring框架最全的Bean工厂, 掌握DefaultListableBeanFactory 是非常有必要的。
我们可以使用DefaultListableBeanFactory 对象注册一个BeanDefition, 使用registerBeanDefinition()方法, 如果想要加入一个BeanPostProcessor, 可以使用addBeanPostProcessor()方法。
private DefaultListableBeanFactory createBeanByDefaultListableBeanFactory(final Class> beanClass) {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);beanDefinition.setInitMethodName("testMethod");beanDefinition.setDestroyMethodName("testDestroy");beanFactory.registerBeanDefinition("testBean", beanDefinition);//添加BeanPostProcessorbeanFactory.addBeanPostProcessor(new BeanPostProcessor() {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {//System.out.println("执行前..");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("执行后..");return bean;}});return beanFactory;}public static class User {public void testMethod(){System.out.println("初始化..");}public void testDestroy(){System.out.println("销毁..");}}@Testpublic void testDefaultListableBeanFactory() {final Class> beanClass = User.class;DefaultListableBeanFactory beanFactory = createBeanByDefaultListableBeanFactory(beanClass);User user = beanFactory.getBean("testBean", User.class);System.out.println("user= " + user);}
打印结果:
从打印结果可以知道User这个Bean的三个方法的执行顺序:
postProcessBeforeIntialization()> init-method()>postProcessAfterInitialization()
DefaultListableBeanFactory里设计了三级缓存,三级缓存只针对单例Bean, 该三级缓存分别是: singletonObjects, earlySingletonObjects, singletonFactoirese。
/** Cache of singleton objects: bean name --> bean instance */
private final Map singletonObjects = new ConcurrentHashMap<>(256);/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map> singletonFactories = new HashMap<>(16);/** Cache of early singleton objects: bean name --> bean instance */
private final Map earlySingletonObjects = new HashMap<>(16);
有依赖的情况下获取Bean:
/*** Return the (raw) singleton object registered under the given name.* Checks already instantiated singletons and also allows for an early* reference to a currently created singleton (resolving a circular reference).* @param beanName the name of the bean to look for* @param allowEarlyReference whether early references should be created or not* @return the registered singleton object, or {@code null} if none found*/@Nullableprotected Object getSingleton(String beanName, boolean allowEarlyReference) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {//尝试从二级缓存里singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {// 从三级缓存里拿到ObjectFactory后,创建一个实例添加到二级缓存里singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}return singletonObject;}
1. 先从一级缓存里拿, 如果有直接返回。
2. 如果从一级缓存里没有拿到Bean的实例,那么尝试从二级缓存里拿,如果有直接返回,没有执行步骤3.
3. 从三级缓存里根据BeanName获取到ObjectFactory接口实例,使用getObject()方法获取到实例后,加入到二级缓存同时返回实例。
由于篇幅过长的问题,后续会单独写一篇Spring框架为什么要设计三级缓存,如果没有三级缓存能不能行?欢迎大家持续关注。
我们都知道Spring 通过自动装配来实现Bean的初始化,当我们在用Bean的依赖属性时都已经完成了初始化,而不是一个Null, 那么Spring 是如何实现IOC的?
在创建Bean时会进入到AutowireCapableBeanFactory的 doCreateBean方法:
两个核心方法分别实现是: 属性填充populateBean、初始化Bean。
进入到populeBean方法,看是如何根据RootBeanDefinition和instanceWrapper来填充的
Populate the bean instance in the given BeanWrapper with the property values.
根据BeanWrapper来填充Bean属性。
AutowireCapableBeanFactory接口里定义了Bean属性的装配方式,我们要核心掌握3种:
根据名称来装配AUTOWIRE_BY_NAME
根据Type来装配AUTOWIRE_BY_TYPE
根据构造器来装配AUTOWIRE_CONSTRUCTOR
/*** Constant that indicates no externally defined autowiring. Note that* BeanFactoryAware etc and annotation-driven injection will still be applied.* @see #createBean* @see #autowire* @see #autowireBeanProperties*/int AUTOWIRE_NO = 0;/*** Constant that indicates autowiring bean properties by name* (applying to all bean property setters).* @see #createBean* @see #autowire* @see #autowireBeanProperties*/int AUTOWIRE_BY_NAME = 1;/*** Constant that indicates autowiring bean properties by type* (applying to all bean property setters).* @see #createBean* @see #autowire* @see #autowireBeanProperties*/int AUTOWIRE_BY_TYPE = 2;/*** Constant that indicates autowiring the greediest constructor that* can be satisfied (involves resolving the appropriate constructor).* @see #createBean* @see #autowire*/int AUTOWIRE_CONSTRUCTOR = 3;/*** Constant that indicates determining an appropriate autowire strategy* through introspection of the bean class.* @see #createBean* @see #autowire* @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,* prefer annotation-based autowiring for clearer demarcation of autowiring needs.*/@Deprecatedint AUTOWIRE_AUTODETECT = 4;
这3个类型分别定义在AbstarctBeanDefinition类里, 在populateBean时会用到, 接着进入到populateBean方法:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw);
根据Name和Type装配Bean:
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// Add property values based on autowire by name if applicable.if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// Add property values based on autowire by type if applicable.if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}
接下来进入autowireByName方法,深入理解是怎么根据name进行装配的。
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {//获取到当前BeanDefinition下所有的属性String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);for (String propertyName : propertyNames) {// 根据name从容器里如果能找到该Beanif (containsBean(propertyName)) {Object bean = getBean(propertyName);// 为依赖的Bean填充属性pvs.add(propertyName, bean);// 将依赖的Bean用map管理起来registerDependentBean(propertyName, beanName);if (logger.isDebugEnabled()) {logger.debug("Added autowiring by name from bean name '" + beanName +"' via property '" + propertyName + "' to bean named '" + propertyName + "'");}}else {if (logger.isTraceEnabled()) {logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +"' by name: no matching bean found");}}}}
先根据unsatisfiedSimpleProperties方法来获取到当前BeanDefinition下所有的属性, 然后从容器里判断Bean是否存在,如果已经存在,那么通过pvs.add(propertyName, bean) 将从容器里拿出的Bean赋值给propertyName对应的Bean。
最后当前Bean依赖的Bean 存放到DefaultSingletonBeanRegistry的dependentBeanMap和dependenciesForBeanMap里缓存起来。
protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {TypeConverter converter = getCustomTypeConverter();if (converter == null) {converter = bw;}Set autowiredBeanNames = new LinkedHashSet<>(4);String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);for (String propertyName : propertyNames) {try {PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);// Don't try autowiring by type for type Object: never makes sense,// even if it technically is a unsatisfied, non-simple property.if (Object.class != pd.getPropertyType()) {MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);// Do not allow eager init for type matching in case of a prioritized post-processor.boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);if (autowiredArgument != null) {//填充属性pvs.add(propertyName, autowiredArgument);}for (String autowiredBeanName : autowiredBeanNames) {// 缓存依赖的BeanregisterDependentBean(autowiredBeanName, beanName);if (logger.isDebugEnabled()) {logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +propertyName + "' to bean named '" + autowiredBeanName + "'");}}autowiredBeanNames.clear();}}catch (BeansException ex) {throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);}}}
为了进一步理解Bean的生命周期,下面我们继续看Aware、BeanPostProcessor、InitialzingBean接口的执行顺序。
initializeBean方法实现了实例化Bean的整个流程。
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction
该方法执行顺序分析:
1. 通过InvokeAwareMethods执行BeanNameAware、BeanFactoryAware、BeanClassLoaderAware接口定义的方法。
2. 执行BeanPostProcessor列表里所有的BeanPostProcessor的PostProcessBeforeInitialization()方法。
3. 通过invokeInitMethod()执行init-method。
4. 执行IntializingBean接口里的AfterPropertiesSet()方法。
5. 执行BeanPostProcessor列表里所有的BeanPostProcessor的PostProcessAfterInitialization()方法。
BeanNameAware、BeanFactoryAware、BeanClassLoaderAware接口分别是在初始化Bean之前调用的,我们可以利用BeanName、BeanFactory、ClassLoader去开发一些业务。
/*** 执行BeanNameAware、BeanClassLoaderAware、BeanFactoryAware的接口。* @param beanName* @param bean*/private void invokeAwareMethods(final String beanName, final Object bean) {if (bean instanceof Aware) {if (bean instanceof BeanNameAware) {((BeanNameAware) bean).setBeanName(beanName);}if (bean instanceof BeanClassLoaderAware) {ClassLoader bcl = getBeanClassLoader();if (bcl != null) {((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);}}if (bean instanceof BeanFactoryAware) {((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}}
BeanPostProcessor在这里是在Aware之后调用的,接着看BeanPostProcessor接口。
BeanPostProcessor接口里有2个默认方法,分别为PostProcessBeforeInitialization和PostProcessAfterInitialization。
public interface BeanPostProcessor {/*** Apply this BeanPostProcessor to the given new bean instance before any bean* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}* or a custom init-method). The bean will already be populated with property values.* The returned bean instance may be a wrapper around the original.* The default implementation returns the given {@code bean} as-is.* @param bean the new bean instance* @param beanName the name of the bean* @return the bean instance to use, either the original or a wrapped one;* if {@code null}, no subsequent BeanPostProcessors will be invoked* @throws org.springframework.beans.BeansException in case of errors* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet*/@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}/*** Apply this BeanPostProcessor to the given new bean instance after any bean* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}* or a custom init-method). The bean will already be populated with property values.* The returned bean instance may be a wrapper around the original.*
In case of a FactoryBean, this callback will be invoked for both the FactoryBean* instance and the objects created by the FactoryBean (as of Spring 2.0). The* post-processor can decide whether to apply to either the FactoryBean or created* objects or both through corresponding {@code bean instanceof FactoryBean} checks.*
This callback will also be invoked after a short-circuiting triggered by a* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,* in contrast to all other BeanPostProcessor callbacks.*
The default implementation returns the given {@code bean} as-is.* @param bean the new bean instance* @param beanName the name of the bean* @return the bean instance to use, either the original or a wrapped one;* if {@code null}, no subsequent BeanPostProcessors will be invoked* @throws org.springframework.beans.BeansException in case of errors* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet* @see org.springframework.beans.factory.FactoryBean*/@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}}
InitializingBean接口官方解释: 当所有的Bean属性被BeanFactory设置完后允许你用afterPropertieSet()方法做一次调。
/*** Interface to be implemented by beans that need to react once all their* properties have been set by a BeanFactory: for example, to perform custom* initialization, or merely to check that all mandatory properties have been set.** An alternative to implementing InitializingBean is specifying a custom* init-method, for example in an XML bean definition.* For a list of all bean lifecycle methods, see the* {@link BeanFactory BeanFactory javadocs}.** @author Rod Johnson* @see BeanNameAware* @see BeanFactoryAware* @see BeanFactory* @see org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName* @see org.springframework.context.ApplicationContextAware*/
public interface InitializingBean {/*** Invoked by a BeanFactory after it has set all bean properties supplied* (and satisfied BeanFactoryAware and ApplicationContextAware).*
This method allows the bean instance to perform initialization only* possible when all bean properties have been set and to throw an* exception in the event of misconfiguration.* @throws Exception in the event of misconfiguration (such* as failure to set an essential property) or if initialization fails.*/void afterPropertiesSet() throws Exception;}
该接口一般可以用来做属性实例的校验,比如当前Bean依赖了哪些Bean, 如果依赖的Bean没有初始化,就应该抛出异常,例如DataSourceTransactionManager里用该方法去校验DataSource有没有被初始化。
public class DataSourceTransactionManager extends AbstractPlatformTransactionManagerimplements ResourceTransactionManager, InitializingBean {@Nullableprivate DataSource dataSource;private boolean enforceReadOnly = false;/*** Create a new DataSourceTransactionManager instance.* A DataSource has to be set to be able to use it.* @see #setDataSource*/public DataSourceTransactionManager() {setNestedTransactionAllowed(true);}/*** Create a new DataSourceTransactionManager instance.* @param dataSource JDBC DataSource to manage transactions for*/public DataSourceTransactionManager(DataSource dataSource) {this();setDataSource(dataSource);afterPropertiesSet();}@Overridepublic void afterPropertiesSet() {if (getDataSource() == null) {throw new IllegalArgumentException("Property 'dataSource' is required");}}}
InitializingBean接口的afterPropertiesSet()在AbstractAutowireCapableBeanFactory的invokeInitMethods方法里被调用。
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)throws Throwable {boolean isInitializingBean = (bean instanceof InitializingBean);// 执行InitializingBean的afterPropertiesSet()if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {if (logger.isDebugEnabled()) {logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");}if (System.getSecurityManager() != null) {try {AccessController.doPrivileged((PrivilegedExceptionAction