前言
早在分析beanFactoryPostProcessor的时候,就出现了BeanFactory.getBean方法,因为每一个beanFactoryPostProcessor也是spring管理的bean,也是要经过spring实例化和初始化才能够使用的,只是当时该方法还不是要分析的重点。
这里多提一句 在初始化过程中容易被忽略的一个方法
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners();
这一步是注册listener,一般可以监听spring的context容器启动完成等情况的,一般开发者也不太会用到
1 查询缓存
final String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); }
这部分是先查询该bean是否在之前有过缓存,有就直接使用了,还有一种情况是该bean是一个beanFactory那么就调用beanFactory的getObject方法
2 从父容器中初始化bean
// Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } }
代码的作用比较清晰
3 开始实例化
try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); getBean(dep); } }
先说一说这个BeanDefinition,BD只是一个接口,常用的实现类是
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable
比如在容器启动的最开始通过BeanDefinitionReader读取的最原始的bd就都是AbstractBeanDefinition
到这里也能够看到 会把 AbstractBeanDefinition 变成了 RootBeanDefinition
注意这里的mergedBeanDefinition,根据文档beanDefinition也是有继承关系的。注意不是真的类的继承关系,我写的代码测试B继承A,但是还是两个BeanDefinition。
mergedBeanDefinitions 是在 AbstractBeanFactory里的
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<String, RootBeanDefinition>(256);
而保存所有的beanDefinition是在 DefaultListableBeanFactory的
/** Map of bean definition objects, keyed by bean name */ private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
总之一句话,一个beanDefinition会经过转换变成mergedBeanDefinition,尽管大多数的beanDefinition还是保持着原样。那么什么情况下会出现需要mergedBeanDefinition呢?如下这种,当然绝大多数没人这么用。
<bean id="baseUser" class="com.yh.stu.spring.sourcestu._01ioc.ch1_base.mergebd.BaseUser"> </bean> <bean id="user" class="com.yh.stu.spring.sourcestu._01ioc.ch1_base.mergebd.User" parent="baseUser"/>
而接下来的实例化一个bean就是使用mergedBeanDefinition。
这里做的第二件事是实例化该bean所依赖的bean。注意这里的dependon并不是指@Autowired这种依赖注入,而是大概这种方式
<bean id="cat" class="com.lyc.cn.day08.Cat" p:name="美美" depends-on="dog"/>
<bean id="helloApi" class="com.feng.spring.chapter2.helloworld.HelloApi"> </bean> <bean id="decorator" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" depends-on="helloApi"> <property name="helloApi"><ref bean="helloApi"/></property> </bean>
同样的上面说的mergedBeanDefinition也不是指两个类之间的继承关系,而是这种通过配置文件配出来的两个bean的关系
<bean id="parentBean" abstract="true"> <property name="name" value="我是父亲"/> </bean> <bean id="sunBean" class="com.lyc.cn.day08.SunBean" parent="parentBean"> <property name="age" value="18"/> </bean>
接下来就是正式的实例化过程了
4 AbstractAutowireCapableBeanFactory.createBean
第一部分 准备工作
if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); }
特别注意,// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. 大多数情况下Spring的动态代理并不是在这里完成的,除非在配置文件里显式的配了
TargetSources,才会走到这里
第二部分 开始实例化
AbstractAutowireCapableBeanFactory.doCreateBean
// Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); }
真正进行实例化的代码就在 createBeanInstance 里,
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); 对于绝大部分bean来说都是通过反射,利用class拿到构造方法,再用构造方法实例化对象,这里不再展开。
回到doCreateBean继续分析
缓存需要依赖注入的元信息
// Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } }
applyMergedBeanDefinitionPostProcessors 的是就是这样的,那么 MergedBeanDefinitionPostProcessor的实现类有哪些呢?还真有一个比较有名的AutowiredAnnotationBeanPostProcessor。AutowiredAnnotationBeanPostProcessor是能够处理@Autowired和@Value这样的注解的。这也和之前介绍BeanPostProcessor里提到的呼应起来了,BeanPostProcessor有两个最特别的子类
1 InstantiationAwareBeanPostProcessor
2 MergedBeanDefinitionPostProcessor
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof MergedBeanDefinitionPostProcessor) { MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp; bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); } } }
我们来看看 AutowiredAnnotationBeanPostProcessor的 postProcessMergedBeanDefinition干了啥。
@Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { if (beanType != null) { InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); } }
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) { // Fall back to class name as cache key, for backwards compatibility with custom callers. String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); // Quick check on the concurrent map first, with minimal locking. InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { synchronized (this.injectionMetadataCache) { metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { if (metadata != null) { metadata.clear(pvs); } try { metadata = buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); }
findAutowiringMetadata方法是很长的,这里只截取一段代码看看意思。
buildAutowiringMetadata构造出来一个要注入的元数据对象,同时缓存在 injectionMetadataCache里面,缓存的key就是
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
InjectionMetadata 是什么呢,就是一个对象里哪个属性是需要注入的(其他的由Spring管理的对象,而不是基本类型)。
这些缓存信息AutowiredAnnotationBeanPostProcessor在后续代码执行中会用到的。
再次回到doCreateBean继续分析
解决循环依赖的
// Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); }
这部分就是解决循环依赖的关键点,把一个实例化好了的bean放进三级缓存里。
属性注入及初始化
最重要的两个方法,populateBean和initializeBean
populateBean是解决一个bean属性注入的。
initializeBean是调用初始化方法的,比如@PostConstruct,配置文件里的init-method,和实现了InitializingBean接口的接口方法
Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { exposedObject = initializeBean(beanName, exposedObject, mbd); } } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } }
分析下populateBean
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; } //上面的代码现在几乎不会走到,都是为了兼容老代码的,而且像@Autowired等注解也不走到里面 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()) {//循环遍历每一个beanPostProcessor调用他们的postProcessPropertyValues if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } }
不妨我们还是以AutowiredAnnotationBeanPostProcessor的 方法来举例
public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException { InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex); } return pvs; }
之前在 缓存需要依赖注入的元信息 这个小节交代过了, 实例化后会处理一个bean中的标签@Autowired并缓存起来。
现在就可以直接用了
拿到 InjectionMetadata metadata 后就调用 inject。
对于autowired来说他对应的 方法是这样的
@Override protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable { Field field = (Field) this.member; Object value; if (this.cached) { value = resolvedCachedArgument(beanName, this.cachedFieldValue); } else { DependencyDescriptor desc = new DependencyDescriptor(field, this.required); desc.setContainingClass(bean.getClass()); Set<String> autowiredBeanNames = new LinkedHashSet<String>(1); TypeConverter typeConverter = beanFactory.getTypeConverter(); try { value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);//把依赖的值解析出来 } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } synchronized (this) { if (!this.cached) { if (value != null || this.required) { this.cachedFieldValue = desc; registerDependentBeans(beanName, autowiredBeanNames); if (autowiredBeanNames.size() == 1) { String autowiredBeanName = autowiredBeanNames.iterator().next(); if (beanFactory.containsBean(autowiredBeanName)) { if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { this.cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } } else { this.cachedFieldValue = null; } this.cached = true; } } } if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value);//反射方法直接塞进去 } }
再说明一下另一个常用的自动注入注解@Resource,也是在 populateBean 中生效的
在CommonAnnotationBeanPostProcessor中方法 buildResourceMetadata中的代码段中
else if (field.isAnnotationPresent(Resource.class)) { if (Modifier.isStatic(field.getModifiers())) { throw new IllegalStateException("@Resource annotation is not supported on static fields"); } if (!ignoredResourceTypes.contains(field.getType().getName())) { currElements.add(new ResourceElement(field, field, null)); } }
如果一个字段头顶有@Resource会保存起来,等待后续处理
上面是处理自动注入其他Bean的逻辑,最后还会执行一下属性静态值的注入,所谓的静态值就是配置文件里明确配了的值,这部分值会在装在BeanDefinition的时候就缓存在BD中
applyPropertyValues(beanName, mbd, bw, pvs); 这部分就不详细说了。
initializeBean
到了执行初始化方法的时候了,这里说的初始化有三种,@PostConstruct,bean实现了initializingBean接口,和配置了init-method方法,这三种情况的执行。
先看代码
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);//就在这里执行的@PostConstruct } try { invokeInitMethods(beanName, wrappedBean, mbd);//先initializingBean接口,而后才是init-method方法
} 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原bean } return wrappedBean; }
调用applyBeanPostProcessorsBeforeInitialization过程中会调用InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization
InitDestroyAnnotationBeanPostProcessor实现了接口 MergedBeanDefinitionPostProcessor 所以呢?在一个Bean实例化成一个空对象的时候,首先就执行过一次
MergedBeanDefinitionPostProcessor的 postProcessMergedBeanDefinition 对元数据进行了缓存,此时就正好拿出来直接使用了
@Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass()); try { metadata.invokeInitMethods(bean, beanName); } catch (InvocationTargetException ex) { throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException()); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Failed to invoke init method", ex); } return bean; }
最终调用
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) { final boolean debug = logger.isDebugEnabled(); LinkedList<LifecycleElement> initMethods = new LinkedList<LifecycleElement>(); LinkedList<LifecycleElement> destroyMethods = new LinkedList<LifecycleElement>(); Class<?> targetClass = clazz; do { final LinkedList<LifecycleElement> currInitMethods = new LinkedList<LifecycleElement>(); final LinkedList<LifecycleElement> currDestroyMethods = new LinkedList<LifecycleElement>(); ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() { @Override public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { if (initAnnotationType != null) { if (method.getAnnotation(initAnnotationType) != null) { LifecycleElement element = new LifecycleElement(method); currInitMethods.add(element); if (debug) { logger.debug("Found init method on class [" + clazz.getName() + "]: " + method); } } }
initAnnotationType是在子类中赋值的,
public CommonAnnotationBeanPostProcessor() { setOrder(Ordered.LOWEST_PRECEDENCE - 3); setInitAnnotationType(PostConstruct.class); setDestroyAnnotationType(PreDestroy.class); ignoreResourceType("javax.xml.ws.WebServiceContext"); }
所以,处理PostConstruct的就是CommonAnnotationBeanPostProcessor。并且面试中常问的初始化顺序问题通过源码也能够知道了。
applyBeanPostProcessorsBeforeInitialization先执行,然后 invokeInitMethods才执行。所以PostConstruct最早执行。
<bean id="helloApi" class="com.feng.spring.chapter2.helloworld.HelloApi"> </bean> <bean id="decorator" class="cn.javass.spring.chapter3.bean.HelloApiDecorator" depends-on="helloApi"> <property name="helloApi"><ref bean="helloApi"/></property> </bean>