运维开发网

关于Bean如何初始化的详细介绍

运维开发网 https://www.qedev.com 2022-05-19 17:17 出处:网络
Spring只Bean加载机制默认情况下是初始化容器的时候就会直接初始化,但是也取决于是否使用了懒加载,下面这篇文章主要给大家介绍了关于Spring?Bean是如何初始化的相关资料,需要的朋友可以参考

Spring只Bean加载机制默认情况下是初始化容器的时候就会直接初始化,但是也取决于是否使用了懒加载,下面这篇文章主要给大家介绍了关于Spring?Bean是如何初始化的相关资料,需要的朋友可以参考


前言

我做Java多年,一直有一个困惑:Spring如何初始化bean,如何调用反射实例化对象?自己动手解决这个难题。以前我以为spring bean对象实例化总是由BeanPostProcessor接口实现类来完成。只是不知道具体实现类。我们来验证一下这个猜想。


三级缓存

为什么面试官特别喜欢问创建豆子三级缓存的事情?主要原因是bean的创建是通过三级缓存之间的转换来完成的,对象的不同状态存在于不同的缓存中。下面,我将在分析代码时支持对象如何在缓存中流动。让我们来看看spring L3缓存。

/** 一级缓存 用于存放完全可以使用单例bean,也就是初始化完成并且注入所有依赖 */private final Maplt;String, Objectgt; singletonObjects = new ConcurrentHashMaplt;gt;(256);/** 二级缓存 过早暴露单例对象,此时bean刚刚完成初始化,未完成属性注入和执行 init 方法 */private final Maplt;String, Objectgt; earlySingletonObjects = new ConcurrentHashMaplt;gt;(16);/** 三级缓存 装载创建bean的工厂对象 */private final Maplt;String, ObjectFactorylt;?gt;gt; singletonFactories = new HashMaplt;gt;(16)

三级缓存的主要作用:创建的对象ObjectFactory首先放在三级缓存中。当调用getObject创建实例时,创建的对象将被添加到二级缓存中,三级缓存将被删除。当对象的初始化方法和属性注入完成后,缓存将被添加到一级缓存中,二级缓存将被删除。


doGetBean

从源码上看,所有spring bean初始化都是通过AbstractBeanFactory.doGetBean方法实现的。下面,我将从源代码中减去臃肿的部分,贴出来。

protected lt;Tgt; T doGetBean(String name, @Nullable Classlt;Tgt; requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException { //name 前缀处理 beanFactory beanName 带有amp;开头String beanName = transformedBeanName(name);Object beanInstance; //从三级缓存去取bean,三级中都没有则返回null,说明对象还没有创建Object sharedInstance = getSingleton(beanName);if (sharedInstance != null amp;amp; args == null) { //如果缓存中bean 是FactoryBean实例,要通过接口获取到实际beanbeanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else { //判断bean对象标记是否正在创建中,如果正在创建中则不应该继续下去,出现依赖循环就会出现这个错误if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}BeanFactory parentBeanFactory = getParentBeanFactory(); // 检查父容器是否存在,尝试从父容器中获取if (parentBeanFactory != null amp;amp; !containsBeanDefinition(beanName)) {String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}else if (args != null) {return (T) parentBeanFactory.getBean(nameToLookup, args);}else if (requiredType != null) {return parentBeanFactory.getBean(nameToLookup, requiredType);}else {return (T) parentBeanFactory.getBean(nameToLookup);}}if (!typeCheckOnly) { //缓存中标记beanName 正在被创建markBeanAsCreated(beanName);}StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);try {if (requiredType != null) {beanCreation.tag("beanType", requiredType::toString);}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) { //bean 中@DependsOn 信息,用于标记bean之间初始化顺序,优先创建@DependsOn 中beanfor (String dep : dependsOn) {if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}registerDependentBean(dep, beanName);try {getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}} //创建单例对象if (mbd.isSingleton()) { //重点就在这里实例化对象 ,getSingleton 就是在这里将创建完成对象加入到一级缓存中sharedInstance = getSingleton(beanName, () -gt; {try {return createBean(beanName, mbd, args);}catch (BeansException ex) destroySingleton(beanName);throw ex;}}); //如果生成bean 是FactoryBean ,再获取真正的对象beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);} //作用域 = prototype,因为不会放入缓存中,每次获取都要重新创建else if (mbd.isPrototype()) {// It's a prototype -gt; create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}else { // session request 这些作用域,由作用域容器去管理这些对象String scopeName = mbd.getScope();if (!StringUtils.hasLength(scopeName)) {throw new IllegalStateException("No scope name defined for bean ′" + beanName + "'");}Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, () -gt; {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new ScopeNotActiveException(beanName, scopeName, ex);}}}catch (BeansException ex) {beanCreation.tag("exception", ex.getClass().toString());beanCreation.tag("message", String.valueOf(ex.getMessage()));cleanupAfterBeanCreationFailure(beanName);throw ex;}finally {beanCreation.end();}} //返回初始化成功的对象,一个对象初始化就这样完成的了 return adaptBeanInstance(name, beanInstance, requiredType); }

总结一下上面的代码流:

先从三级缓存中获取,如果缓存中都没有。再去判断是否存在父容器,从父容器中获取。没有正式进入bean 初始化流程,先根据beanName 获取到RootBeanDefinition,bean类元信息、先处理dependsOn中bean,保证bean依赖的创建顺序,下面会说明org.springframework.context.annotation.@DependsOn这个注解。下一步按照不同scope 进行bean 对象初始化。初始化流程就是这样,我们将目光放在单例bean 如何实例化,集中关注AbstractAutowireCapableBeanFactory.createBean 获取注册一个单例对象

@DependsOn批注的意思是实例化一个对象依赖于一个实例化,但是没有必要持有这个实例对象。比如bean A需要依赖bean b进行实例化,但是bean b不需要成为他的属性,经常用于标记不同实例的实例化顺序。

看看getSingleton方法

public Object getSingleton(String beanName, ObjectFactorylt;?gt; singletonFactory) {synchronized (this.singletonObjects) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {if (this.singletonsCurrentlyInDestruction) { //标记bean 是否在销毁throw new BeanCreationNotAllowedException(beanName,"Singleton bean creation not allowed while singletons of this factory are in destruction " +"(Do not request a bean from a BeanFactory in a destroy method implementation!)");}beforeSingletonCreation(beanName);boolean newSingleton = false;boolean recordSuppressedExceptions = (this.suppressedExceptions == null);if (recordSuppressedExceptions) {this.suppressedExceptions = new LinkedHashSetlt;gt;();}try {singletonObject = singletonFactory.getObject();newSingleton = true;}catch (IllegalStateException ex) {}catch (BeanCreationException ex) {throw ex;}finally {if (recordSuppressedExceptions) {this.suppressedExceptions = null;}afterSingletonCreation(beanName);}if (newSingleton) {addSingleton(beanName, singletonObject); //就是在这里删除二三级缓存,提交到一级缓存}}return singletonObject;}}protected void addSingleton(String beanName, Object singletonObject) {synchronized (this.singletonObjects) {this.singletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}}

添加到一级缓存表示bean已经实例化,可以正常使用。让我们看看如何实例化和注入属性。


createBean

我们转到abstracttautowirecapablebean factory . create bean。

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {RootBeanDefinition mbdToUse = mbd; //克隆一份mbd =gt; mbdToUseClasslt;?gt; resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null amp;amp; !mbd.hasBeanClass() amp;amp; 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. //通过BeanPostProcessors 增强返回一个代理对象,这个生成AOP的代理对象,使用多个BeanPostProcessors来处理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);}try { // bean 对象实例化就这里实现Object beanInstance = doCreateBean(beanName, mbdToUse, args);return beanInstance;}catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {throw ex;}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);}}

这里的逻辑很简单。克隆一个RootBeanDefinition来初始化对象,resolveBeforeInstantiation主要用于初始化代理对象。主BeanPostProcessor子类instantiationwarebeanpostprocessor用于实现对象初始化,成功实例化后调用post方法注入对象依赖。这里我们可以看到这个方法返回的对象直接跳出了方法栈。在这里,我们可以看到单一对象和代理对象之间还是有区别的。单实例对象初始化在doCreateBean中实现。


doCreateBean

以下是towirecapablebeanfactory的摘要。DocreateBean非常接近对象的实例化方式。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable 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); //这个就是实例化方法}Object bean = instanceWrapper.getWrappedInstance();Classlt;?gt; beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// 使用BeanDefinitionPostProcessors 对合并bean进行实例化 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;}}// 这里就需要用到上面说的三级缓存知识了// even when triggered by lifecycle interfaces like BeanFactoryAware.boolean earlySingletonExposure = (mbd.isSingleton() amp;amp; this.allowCircularReferences amp;amp;isSingletonCurrentlyInCreation(beanName)); //是否放入第三级缓存中if (earlySingletonExposure) {if (logger.isTraceEnabled()) {logger.trace("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}addSingletonFactory(beanName, () -gt; getEarlyBeanReference(beanName, mbd, bean)); //将已经实例化的对象加入到第三级缓存 singletonFactories }// Initialize the bean instance.Object exposedObject = bean;try {populateBean(beanName, mbd, instanceWrapper); //对属性进入注入,下面会具体分析的exposedObject = initializeBean(beanName, exposedObject, mbd); //执行初始化方法,或者注入Aware 接口bean}catch (Throwable ex) {if (ex instanceof BeanCreationException amp;amp; beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}//下面代码省略 //主要就是对设置了DisposableBean 接口销毁钩子方法处理}

这里的代码主要分为三个部分。

初始化实例,创建对象完成,并且添加到3级缓存。第3级缓存常常用于存储代理对象,因为有些类需要动态代理方法,需要生成代理对象,会委派给第三级缓存方法ObjectFactroy去实现的,普通对象如果不需要会直接返回。对实例化bean进行属性注入执行初始化方法,DisposableBean接口加入到disposableBeans容器中


instantiateBeanprotected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {// Make sure bean class is actually resolved at this point.Classlt;?gt; beanClass = resolveBeanClass(mbd, beanName);if (beanClass != null amp;amp; !Modifier.isPublic(beanClass.getModifiers()) amp;amp; !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());}Supplierlt;?gt; instanceSupplier = mbd.getInstanceSupplier();if (instanceSupplier != null) {// 有实现Supplier 接口,由instanceSupplier.get() 方法创建实例return obtainFromSupplier(instanceSupplier, beanName);} //factoryName 使用工厂模式创建bean,调用工厂方法去创建,这个支持静态方法和factoryBean.invokeif (mbd.getFactoryMethodName() != null) {return instantiateUsingFactoryMethod(beanName, mbd, args);}// Shortcut when re-creating the same bean...boolean resolved = false; //标记构造函数是否需要参数boolean autowireNecessary = false; //标记构造方法的参数是否使用注入方式if (args == null) {synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null) {resolved = true;autowireNecessary = mbd.constructorArgumentsResolved;}}}if (resolved) {if (autowireNecessary) { //使用构造函数注入方式实例化return autowireConstructor(beanName, mbd, null, null);}else { //实例化对象return instantiateBean(beanName, mbd);}}// 获取构造函数参数Constructorlt;?gt;[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);}// Preferred constructors for default construction?ctors = mbd.getPreferredConstructors();if (ctors != null) {return autowireConstructor(beanName, mbd, ctors, null);}// No special handling: simply use no-arg constructor.return instantiateBean(beanName, mbd);}

实例化方法instantiateBean最终将调用SimpleInstationStrategy。实例化实例化。


instantiatepublic Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {// Don't override the class with CGLIB if no overrides.if (!bd.hasMethodOverrides()) {Constructorlt;?gt; constructorToUse;synchronized (bd.constructorArgumentLock) {constructorToUse = (Constructorlt;?gt;) bd.resolvedConstructorOrFactoryMethod;if (constructorToUse == null) {final Classlt;?gt; clazz = bd.getBeanClass();if (clazz.isInterface()) {throw new BeanInstantiationException(clazz, "Specified class is an interface");}try {if (System.getSecurityManager() != null) {constructorToUse = AccessController.doPrivileged((PrivilegedExceptionActionlt;Constructorlt;?gt;gt;) clazz::getDeclaredConstructor);}else {constructorToUse = clazz.getDeclaredConstructor(); //获取构造函数}bd.resolvedConstructorOrFactoryMethod = constructorToUse;}catch (Throwable ex) {throw new BeanInstantiationException(clazz, "No default constructor found", ex);}}}return BeanUtils.instantiateClass(constructorToUse); //调用构造函数进行实例化}else {// Must generate CGLIB subclass.return instantiateWithMethodInjection(bd, beanName, owner);}}


instantiateClass@Overridepublic Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {// Don't override the class with CGLIB if no overrides.if (!bd.hasMethodOverrides()) {Constructorlt;?gt; constructorToUse;synchronized (bd.constructorArgumentLock) {constructorToUse = (Constructorlt;?gt;) bd.resolvedConstructorOrFactoryMethod;if (constructorToUse == null) {final Classlt;?gt; clazz = bd.getBeanClass();if (clazz.isInterface()) {throw new BeanInstantiationException(clazz, "Specified class is an interface");}try {if (System.getSecurityManager() != null) {constructorToUse = AccessController.doPrivileged((PrivilegedExceptionActionlt;Constructorlt;?gt;gt;) clazz::getDeclaredConstructor);}else {constructorToUse = clazz.getDeclaredConstructor();}bd.resolvedConstructorOrFactoryMethod = constructorToUse;}catch (Throwable ex) {throw new BeanInstantiationException(clazz, "No default constructor found", ex);}}}return BeanUtils.instantiateClass(constructorToUse); //调用构造器进行初始化}else {// Must generate CGLIB subclass.return instantiateWithMethodInjection(bd, beanName, owner);}}

这里要注意首先判断是否有重写bean的方法。如果没有方法,我们就用反射生成的构造函数。如果有,我们将使用gclib创建代理对象。具体实现方法在org。Spring框架。beans . factory . support . simpleinstallationstrategy . instantiate .有兴趣的同学可以学习一下。至此,简单bean的实例化就完成了。


注入

让我们转到IOC的另一个特性,bean注入,从AbstractTautowireCapableBeanfactory方法开始。PopulateBean。

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {// 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. //通过InstantiationAwareBeanPostProcessors.postProcessAfterInstantiation 如果返回true,目标实例内部的返回值会被populate,否则populate这个过程会被忽视 //翻译说如果返回true可以执行字段注入 真的6666啊if (!mbd.isSynthetic() amp;amp; hasInstantiationAwareBeanPostProcessors()) {for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return;}}}PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); //获取注入方式分布有4种int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// Add property values based on autowire by name if applicable.if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// Add property values based on autowire by type if applicable.if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); //依赖方式,模式都是没有类型检查,这种依赖方式一般都是xml 配置用得比较多,没有配置这里都是返回falseboolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); /PropertyDescriptor[] filteredPds = null;if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); //获取注解标注需要注入方法或者是字段,并且进行注入if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}}if (needsDepCheck) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}checkDependencies(beanName, mbd, filteredPds, pvs);}if (pvs != null) {applyPropertyValues(beanName, mbd, bw, pvs);}}

小知识点:autowirecapbleBeanfactory。autowire _ no表示当前bean不会被注入外部类。常规使用的@Autowire和@Resource就是这种类型,剩下的三个都是通过xml或者autowirecapblebeanfactory。自动布线(classlt?gt;Class,int autowireMode,boolean dependency check)来设置autowireMode。

根据上面的代码可以知道,主进程的bean注入都是由InstantiationAware后处理器处理的,所以简单说明一下接口方法。

方法描述postProcessBeforeInitialization方法是最 先执行的方法,它在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走postProcessAfterInitialization方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。因为它的返回值是决定要不要调用postProcessPropertyValues方法的其中一个因素(因为还有一个因素是mbd.getDependencyCheck());如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会被忽略不执行;如果返回true,postProcessPropertyValues就会被执行postProcessPropertyValues对bean属性值赋值后调用,对属性值的修改。如果postProcessAfterInstantiation方法返回false,该方法可能不会被调用。可以在该方法内对属性值进行修改postProcessPropertiesBean属性赋值就是调用这个方法的

InstantiationAware后处理器接口实现类主要分为三类。

ConfigurationClassPostProcessor:看类名就知道处理@Configuration实例化,并没有属性注入逻辑,不详讲略过。CommonAnnotationBeanPostProcessor:这个类就是实现bean注入,但是是实现JSR-250 注解、@Resource,@EJB、@WebServiceRef,@WebServiceContext,@PostConstrusct、@PreDestory这些注解实现。AutowiredAnnotationBeanPostProcessor:实现 @Autowired、@Value注入,并且支持JSR-330#39;s @Inject,主要分析这个类就可以知道bean 注入的。


AutowiredAnnotationBeanPostProcessor分析private final Setlt;Classlt;? extends Annotationgt;gt; autowiredAnnotationTypes = new LinkedHashSetlt;gt;(4);@SuppressWarnings("unchecked")public AutowiredAnnotationBeanPostProcessor() {this.autowiredAnnotationTypes.add(Autowired.class);this.autowiredAnnotationTypes.add(Value.class);try {this.autowiredAnnotationTypes.add((Classlt;? extends Annotationgt;)ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");}catch (ClassNotFoundException ex) {// JSR-330 API not available - simply skip.}}

在初始化时,支持注释被添加到集合中,然后使用扫描器来扫描方法、构造函数和字段,如果有注释,就注入这些注释。

我们来看看如何确定是否需要注射。

@Nullableprivate MergedAnnotationlt;?gt; findAutowiredAnnotation(AccessibleObject ao) {MergedAnnotations annotations = MergedAnnotations.from(ao);for (Classlt;? extends Annotationgt; type : this.autowiredAnnotationTypes) {MergedAnnotationlt;?gt; annotation = annotations.get(type);if (annotation.isPresent()) {return annotation;}}return null;}

AccessibleObject是方法、字段和构造函数的父类。


postProcessProperties 如何实现bean注入的public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { //获取需要注入字段,方法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;} //下面就行获取InjectionMetadata private InjectionMetadata findAutowiringMetadata(String beanName, Classlt;?gt; clazz, @Nullable PropertyValues pvs) {// Fall back to class name as cache key, for backwards compatibility with custom callers.String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());// 快速从缓存中获取,如果没有加锁去解析,然后在结果放入缓存中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);}metadata = buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); }}}return metadata;}InjectionMetadata 主要是集合bean需要被注入类型,因为已经解析过bean Class信息了,相当于解析结果装起来

查看如何扫描方法和字段。

private InjectionMetadata buildAutowiringMetadata(final Classlt;?gt; clazz) { //从给定注解中判断class 是否携带这个注解if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) { return InjectionMetadata.EMPTY;}Listlt;InjectionMetadata.InjectedElementgt; elements = new ArrayListlt;gt;();Classlt;?gt; targetClass = clazz;do {final Listlt;InjectionMetadata.InjectedElementgt; currElements = new ArrayListlt;gt;(); //遍历所有Field,找出扫描的注解,特意标注不支持static 修饰field ReflectionUtils.doWithLocalFields(targetClass, field -gt; {MergedAnnotationlt;?gt; ann = findAutowiredAnnotation(field);if (ann != null) {if (Modifier.isStatic(field.getModifiers())) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation is not supported on static fields: " + field);}return;} // 获取注解内 required 值boolean required = determineRequiredStatus(ann);currElements.add(new AutowiredFieldElement(field, required));}});ReflectionUtils.doWithLocalMethods(targetClass, method -gt; { //获取方法上桥接方法,因为泛型类型擦除,要对桥接方法进行安全检查,防止在调用是出现异常Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {return;} //获取注解MergedAnnotationlt;?gt; ann = findAutowiredAnnotation(bridgedMethod); //方法安全检查if (ann != null amp;amp; method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {if (Modifier.isStatic(method.getModifiers())) { //不支持静态方法注入if (logger.isInfoEnabled()) {logger.info("Autowired annotation is not supported on static methods: " + method);}return;}if (method.getParameterCount() == 0) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation should only be used on methods with parameters: " +method);}}boolean required = determineRequiredStatus(ann);PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);currElements.add(new AutowiredMethodElement(method, required, pd));}}); // 这样写是为了后面加入排在队列前面,父类属性优先于子类elements.addAll(0, currElements);targetClass = targetClass.getSuperclass();}while (targetClass != null amp;amp; targetClass != Object.class); //这里写得很好,向上解析父类,直到是Object 为止return InjectionMetadata.forElements(elements, clazz);}

逻辑很简单,就是根据给定的注释,去class获取指定的注释,从而得到需要注入的类型。但是简单的几行代码就能显示出强大的编码能力。学习??。既然已经获得了要注射的对象,那就来看看怎么注射吧。

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {Collectionlt;InjectedElementgt; checkedElements = this.checkedElements;Collectionlt;InjectedElementgt; elementsToIterate =(checkedElements != null ? checkedElements : this.injectedElements);if (!elementsToIterate.isEmpty()) {for (InjectedElement element : elementsToIterate) {element.inject(target, beanName, pvs);}}}@Overrideprotected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {Field field = (Field) this.member;Object value;if (this.cached) {try {value = resolvedCachedArgument(beanName, this.cachedFieldValue);}catch (NoSuchBeanDefinitionException ex) {// Unexpected removal of target bean for cached argument -gt; re-resolvevalue = resolveFieldValue(field, bean, beanName);}}else {value = resolveFieldValue(field, bean, beanName);}if (value != null) {ReflectionUtils.makeAccessible(field);field.set(bean, value);}}private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {DependencyDescriptor desc = new DependencyDescriptor(field, this.required);desc.setContainingClass(bean.getClass());Setlt;Stringgt; autowiredBeanNames = new LinkedHashSetlt;gt;(1);Assert.state(beanFactory != null, "No BeanFactory available");TypeConverter typeConverter = beanFactory.getTypeConverter(); //类型转换器Object value;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) {Object cachedFieldValue = null;if (value != null || this.required) {cachedFieldValue = desc; // 将注入关系添加到容器中,方便bean销毁时同步销毁registerDependentBeans(beanName, autowiredBeanNames);if (autowiredBeanNames.size() == 1) {String autowiredBeanName = autowiredBeanNames.iterator().next();if (beanFactory.containsBean(autowiredBeanName) amp;amp;beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { //这些都是为了缓存起来cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName, field.getType());}}}this.cachedFieldValue = cachedFieldValue;this.cached = true;}}return value;}}

核心是如果从缓存中得到需要注入的类型实例,在bean factory . resolved dependency中输入DefaultListableBeanFactory

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,@Nullable Setlt;Stringgt; autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());if (Optional.class == descriptor.getDependencyType()) {return createOptionalDependency(descriptor, requestingBeanName);}else if (ObjectFactory.class == descriptor.getDependencyType() ||ObjectProvider.class == descriptor.getDependencyType()) {return new DependencyObjectProvider(descriptor, requestingBeanName);}else if (javaxInjectProviderClass == descriptor.getDependencyType()) {return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);}else { //懒加载 扫描@Lazy注解,返回一个代理对象Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);if (result == null) {result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);}return result;}}

@Lazy使用注释来修饰bean或Class,不会在容器初始化时立即创建,而是只要需要使用bean就会创建。根据可选、ObjectFactory、Provider和lazy loading场景的类型,这些过程的本质是调用doResolveDependency方法来初始化对象。无论是哪种对象,都必须获取原始对象,然后交给这些接口进行包装和增强。

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,@Nullable Setlt;Stringgt; autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { //如果这个注入是通过构造器注入,可以从构造器解析缓存中去获取注入信息点 InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);try {Object shortcut = descriptor.resolveShortcut(this);if (shortcut != null) {return shortcut;}Classlt;?gt; type = descriptor.getDependencyType(); //尝试从注解中获取默认值 @Value 的value Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);if (value != null) {if (value instanceof String) {String strVal = resolveEmbeddedValue((String) value);BeanDefinition bd = (beanName != null amp;amp; containsBean(beanName) ?getMergedBeanDefinition(beanName) : null);value = evaluateBeanDefinitionString(strVal, bd);}TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());try {return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());}catch (UnsupportedOperationException ex) {// A custom TypeConverter which does not support TypeDescriptor resolution...return (descriptor.getField() != null ?converter.convertIfNecessary(value, type, descriptor.getField()) :converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));}} //多种混合类型处理,stream、collection、Map Array 这些Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);if (multipleBeans != null) {return multipleBeans;} //根据类型获取容器中bean名,返回map key就是bean名,value 初始从容器中获取对象,如果没有找到就会抛出异常了Maplt;String, Objectgt; matchingBeans = findAutowireCandidates(beanName, type, descriptor);if (matchingBeans.isEmpty()) {if (isRequired(descriptor)) {raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}return null;}String autowiredBeanName;Object instanceCandidate;if (matchingBeans.size() gt; 1) { //出现一个类型,不同实例,可以根据@Primary, @Priority、属性名方式去配置autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);if (autowiredBeanName == null) {if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { //没有确定,抛出异常return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);}else {return null;}}instanceCandidate = matchingBeans.get(autowiredBeanName);}else {// We have exactly one match.Map.Entrylt;String, Objectgt; entry = matchingBeans.entrySet().iterator().next();autowiredBeanName = entry.getKey();instanceCandidate = entry.getValue();}if (autowiredBeanNames != null) {autowiredBeanNames.add(autowiredBeanName);}if (instanceCandidate instanceof Class) { //这里其实就是从容器中获取实例,如果这时候没有初始化,就走上面初始化流程instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);}Object result = instanceCandidate;if (result instanceof NullBean) {if (isRequired(descriptor)) {raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);}result = null;}if (!ClassUtils.isAssignableValue(type, result)) {throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());}return result;}finally {ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);}}

这个方法是一个简单的总结。首先,处理@Value情况,然后通过findAutowireCandidates按类型从容器中获取实例。如果实例尚未初始化,将调用上述初始化过程,并返回初始化后的对象。根据注入类型,如流和集合,直接添加这些混合类型。如果一个类型有多个bean,则是@Primary和@Priority的注释根据属性名判断或匹配beanName,最后返回bean对象。下面简单看一下bean的初始化过程。


总结

现在我知道Bean实例化是由策略模式创建的,使用反射攻击类,和BeanPostProcessor没有太大关系。刚开始学spring的时候,老师说@Autowired和@Resources注入比较,基于类型和beanName,不完全正确。他通过类型获取bean,如果一个类型有多个beanName,就通过bean和属性名注入。用了这么多年Spring,从来没用过@DependsOn、@Primary、@Priority、@Lookup。如果不看源代码,我不知道这个功能。看完整个源代码,我们对bean生命周期-bean实例化-gt有了清晰的认识;属性注入-gt;执行方法-gt;添加弹簧容器

关于SpringBean如何初始化的这篇文章到此为止。关于SpringBean初始化的更多信息

0

精彩评论

暂无评论...
验证码 换一张
取 消