【Spring源码分析系列】bean的加载
前言
以 BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beans.xml"));为例查看bean的加载过程。
一、首先来看Spring中是如何实现的
1 @Override2 public Object getBean(String name) throwsBeansException {3 return getBean(name, Object.class);4 }5 6 @Override7 public <T> T getBean(String name, Class<T> requiredType) throwsBeansException {8 try{9 if(isSingleton(name)) {10 returndoGetSingleton(name, requiredType);11 }12 else{13 returnlookup(name, requiredType);14 }15 }16 catch(NameNotFoundException ex) {17 throw new NoSuchBeanDefinitionException(name, "not found in JNDI environment");18 }19 catch(TypeMismatchNamingException ex) {20 throw newBeanNotOfRequiredTypeException(name, ex.getRequiredType(), ex.getActualType());21 }22 catch(NamingException ex) {23 throw new BeanDefinitionStoreException("JNDI environment", name, "JNDI lookup failed", ex);24 }25 }
1 //检查要加载的bean是否是单例 2 @Override3 public boolean isSingleton(String name) throwsNoSuchBeanDefinitionException {4 return this.shareableResources.contains(name);5 }
//如果是单例的话从单例的map中获取bean,如果有的话说明已经加载则直接从map中获取,如果没有则将bean放入单例类的map中,单例在Spring的容器中只会被创建一次,后续再获取bean,就直接从单例缓存获取了。当日这里只是尝试加载,首先尝试从缓存中加载,如果加载不成功则再次尝试从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,在Spring中场景bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光到缓存中,一旦下一个bean创建时候需要依赖上一个bean则直接使用ObjectFactory. @SuppressWarnings("unchecked")private <T> T doGetSingleton(String name, Class<T> requiredType) throwsNamingException {synchronized (this.singletonObjects) {if (this.singletonObjects.containsKey(name)) {Object jndiObject= this.singletonObjects.get(name);if (requiredType != null && !requiredType.isInstance(jndiObject)) {throw newTypeMismatchNamingException(convertJndiName(name), requiredType, (jndiObject!= null ? jndiObject.getClass() : null));}return(T) jndiObject;}T jndiObject=lookup(name, requiredType);this.singletonObjects.put(name, jndiObject);returnjndiObject;}}
1 //实例化Bean 2 /** 3 * Perform an actual JNDI lookup for the given name via the JndiTemplate.4 * <p>If the name doesn't begin with "java:comp/env/", this prefix is added5 * if "resourceRef" is set to "true".6 *@paramjndiName the JNDI name to look up7 *@paramrequiredType the required type of the object8 *@returnthe obtained object9 *@throwsNamingException if the JNDI lookup failed10 *@see#setResourceRef11 */ 12 protected <T> T lookup(String jndiName, Class<T> requiredType) throwsNamingException {13 Assert.notNull(jndiName, "'jndiName' must not be null");14 String convertedName =convertJndiName(jndiName);15 T jndiObject;16 try{17 jndiObject =getJndiTemplate().lookup(convertedName, requiredType);18 }19 catch(NamingException ex) {20 if (!convertedName.equals(jndiName)) {21 //Try fallback to originally specified name... 22 if(logger.isDebugEnabled()) {23 logger.debug("Converted JNDI name [" + convertedName + 24 "] not found - trying original name [" + jndiName + "]. " +ex);25 }26 jndiObject =getJndiTemplate().lookup(jndiName, requiredType);27 }28 else{29 throwex;30 }31 }32 if(logger.isDebugEnabled()) {33 logger.debug("Located object with JNDI name [" + convertedName + "]");34 }35 returnjndiObject;36 }
二、FactoryBean的使用
一般情况下,Spring通过反射机制利用bean的class属性指定实现类来实例化bean.在某些情况下,实例化bean过程比较复杂,如果按照传统的方式,则需要在<bean>中提供大量的配置信息,配置信息的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.beans.factory.FactoryBean<T>的工厂类接口,可以通过实现该接口定制实例化bean的逻辑。
FactoryBean接口对于Spring框架来说是非常重要的,Spring自身就提供了70多个FactoryBean的实现,他们影藏了一些实例化复杂bean的细节,给上层应用带来了便利。
该接口中的方法
1 /* 2 * Copyright 2002-2016 the original author or authors.3 *4 * Licensed under the Apache License, Version 2.0 (the "License");5 * you may not use this file except in compliance with the License.6 * You may obtain a copy of the License at7 *8 *http://www.apache.org/licenses/LICENSE-2.0 9 *10 * Unless required by applicable law or agreed to in writing, software11 * distributed under the License is distributed on an "AS IS" BASIS,12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13 * See the License for the specific language governing permissions and14 * limitations under the License.15 */ 16 17 packageorg.springframework.beans.factory;18 19 /** 20 * Interface to be implemented by objects used within a {@linkBeanFactory} which21 * are themselves factories for individual objects. If a bean implements this22 * interface, it is used as a factory for an object to expose, not directly as a23 * bean instance that will be exposed itself.24 *25 * <p><b>NB: A bean that implements this interface cannot be used as a normal bean.</b>26 * A FactoryBean is defined in a bean style, but the object exposed for bean27 * references ({@link#getObject()}) is always the object that it creates.28 *29 * <p>FactoryBeans can support singletons and prototypes, and can either create30 * objects lazily on demand or eagerly on startup. The {@linkSmartFactoryBean}31 * interface allows for exposing more fine-grained behavioral metadata.32 *33 * <p>This interface is heavily used within the framework itself, for example for34 * the AOP {@linkorg.springframework.aop.framework.ProxyFactoryBean} or the35 * {@linkorg.springframework.jndi.JndiObjectFactoryBean}. It can be used for36 * custom components as well; however, this is only common for infrastructure code.37 *38 * <p><b>{@codeFactoryBean} is a programmatic contract. Implementations are not39 * supposed to rely on annotation-driven injection or other reflective facilities.</b>40 * {@link#getObjectType()} {@link#getObject()} invocations may arrive early in41 * the bootstrap process, even ahead of any post-processor setup. If you need access42 * other beans, implement {@linkBeanFactoryAware} and obtain them programmatically.43 *44 * <p>Finally, FactoryBean objects participate in the containing BeanFactory's45 * synchronization of bean creation. There is usually no need for internal46 * synchronization other than for purposes of lazy initialization within the47 * FactoryBean itself (or the like).48 *49 *@authorRod Johnson50 *@authorJuergen Hoeller51 *@since08.03.200352 *@seeorg.springframework.beans.factory.BeanFactory53 *@seeorg.springframework.aop.framework.ProxyFactoryBean54 *@seeorg.springframework.jndi.JndiObjectFactoryBean55 */ 56 public interface FactoryBean<T>{57 58 /** 59 *返回由FactoryBean创建的bean实例,如果isSingleton返回true则该实例会放到Spring容器中单实例缓存池中60 * Return an instance (possibly shared or independent) of the object61 * managed by this factory.62 * <p>As with a {@linkBeanFactory}, this allows support for both the63 * Singleton and Prototype design pattern.64 * <p>If this FactoryBean is not fully initialized yet at the time of65 * the call (for example because it is involved in a circular reference),66 * throw a corresponding {@linkFactoryBeanNotInitializedException}.67 * <p>As of Spring 2.0, FactoryBeans are allowed to return {@codenull}68 * objects. The factory will consider this as normal value to be used; it69 * will not throw a FactoryBeanNotInitializedException in this case anymore.70 * FactoryBean implementations are encouraged to throw71 * FactoryBeanNotInitializedException themselves now, as appropriate.72 *@returnan instance of the bean (can be {@codenull})73 *@throwsException in case of creation errors74 *@seeFactoryBeanNotInitializedException75 */ 76 T getObject() throwsException;77 78 /** 79 *返回FactoryBean创建的bean类型80 * Return the type of object that this FactoryBean creates,81 * or {@codenull} if not known in advance.82 * <p>This allows one to check for specific types of beans without83 * instantiating objects, for example on autowiring.84 * <p>In the case of implementations that are creating a singleton object,85 * this method should try to avoid singleton creation as far as possible;86 * it should rather estimate the type in advance.87 * For prototypes, returning a meaningful type here is advisable too.88 * <p>This method can be called <i>before</i> this FactoryBean has89 * been fully initialized. It must not rely on state created during90 * initialization; of course, it can still use such state if available.91 * <p><b>NOTE:</b> Autowiring will simply ignore FactoryBeans that return92 * {@codenull} here. Therefore it is highly recommended to implement93 * this method properly, using the current state of the FactoryBean.94 *@returnthe type of object that this FactoryBean creates,95 * or {@codenull} if not known at the time of the call96 *@seeListableBeanFactory#getBeansOfType97 */ 98 Class<?>getObjectType();99 100 /** 101 *返回由FactoryBean创建的bean实例的作用域是singleton还是prototype102 * Is the object managed by this factory a singleton? That is,103 * will {@link#getObject()} always return the same object104 * (a reference that can be cached)?105 * <p><b>NOTE:</b> If a FactoryBean indicates to hold a singleton object,106 * the object returned from {@codegetObject()} might get cached107 * by the owning BeanFactory. Hence, do not return {@codetrue}108 * unless the FactoryBean always exposes the same reference.109 * <p>The singleton status of the FactoryBean itself will generally110 * be provided by the owning BeanFactory; usually, it has to be111 * defined as singleton there.112 * <p><b>NOTE:</b> This method returning {@codefalse} does not113 * necessarily indicate that returned objects are independent instances.114 * An implementation of the extended {@linkSmartFactoryBean} interface115 * may explicitly indicate independent instances through its116 * {@linkSmartFactoryBean#isPrototype()} method. Plain {@linkFactoryBean}117 * implementations which do not implement this extended interface are118 * simply assumed to always return independent instances if the119 * {@codeisSingleton()} implementation returns {@codefalse}.120 *@returnwhether the exposed object is a singleton121 *@see#getObject()122 *@seeSmartFactoryBean#isPrototype()123 */ 124 booleanisSingleton();125 126 }
当配置文件中<bean>的class配置的实现类是FactoryBean时,通过getbean()方法返回的不是FactoryBean本身,而是FactoryBean#getObject()方法所返回的对象,相当于FactoryBean#getObject()代理了getBean()方法。
1 <bean id="car" class="com.slp.factorybean.CarFactoryBean" carInfo="BMW,400,200000"/>
当调用getBean("car")时,Spring通过反射机制发现CarFactoryBean实现了FactoryBean的接口,这时Spring容器就调用接口方法CarFactoryBean#getObject()方法返回,如果希望获取CarFactoryBean的实例则需要使用getBean(beanName)方法时在beanName前显式的加上&前缀,例如getBean("&car");
三、从缓存中获取单例bean
介绍过FactoryBean的用法之后,就可以了解bean加载的过程了。单例在Spring的同一个容器内只会被创建一次,后续再获取bean直接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,然后再次尝试从singletonFactorry加载因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,Spring创建bean的原则不等bean创建完成就会创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时需要依赖上个bean,则直接使用ObjectFactory.
四、从bean的实例中获取对象
在getBean方法中,getObjectForBeanInstance是个使用非常多的方法,,物流是从缓存中获得bean还是根据不同的scope策略加载bean,宗旨我们得到bean的第一步就是用这个方法检测其正确性。也就是检测当前bean是否是FactoryBean类型的bean,如果是那么需要调用该bean对应的FactoryBean实例中的getObject()作为返回值。
无论是从缓存中获取到的bean还是通过不同的scope策略加载的bean都只是最原始的bena状态,并不一定是我们最终想要的bean.
五、循环依赖
循环依赖其实就是循环引用,循环调用时无法解决的,除非有终结条件,否则就是死循环,最终导致内存溢出错误。
Spring容器循环依赖包括构造器循环依赖个setter循环依赖。
1、构造器循环依赖
通过构造器注入构成的循环依赖,此依赖是无法解决的,只能抛出BeanCurrentlyInCreationException异常表示循环依赖。
Spring容器将每一个正在创建的bean标识符放在一个“当前创建bean池”中,bean标识符在创建过程中将一直保持在这个池中,因此如果在创建bean的过程中发现自己已经在“当前创建bean池”里时,将抛出BeanCurrentlyInCreationException异常表示循环依赖,而对于创建完毕的bean将从“当前创建bean池”中清除掉。
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testA' defined in class path resource [beans2.xml]: Cannot resolve reference to bean 'testB' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testB' defined in class path resource [beans2.xml]: Cannot resolve reference to bean 'testC' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testC' defined in class path resource [beans2.xml]: Cannot resolve reference to bean 'testA' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'testA': Requested bean is currently in creation: Is there an unresolvable circular reference?
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testA' defined in class path resource [beans2.xml]: Cannot resolve reference to bean 'testB' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testB' defined in class path resource [beans2.xml]: Cannot resolve reference to bean 'testC' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testC' defined in class path resource [beans2.xml]: Cannot resolve reference to bean 'testA' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'testA': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:634)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:145)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1193)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1095)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.slp.TestConfig.main(TestConfig.java:24)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testB' defined in class path resource [beans2.xml]: Cannot resolve reference to bean 'testC' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testC' defined in class path resource [beans2.xml]: Cannot resolve reference to bean 'testA' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'testA': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:634)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:145)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1193)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1095)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 17 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testC' defined in class path resource [beans2.xml]: Cannot resolve reference to bean 'testA' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'testA': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:634)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:145)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1193)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1095)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 29 more
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'testA': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:347)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 41 more
2、setter循环依赖
表示通过setter注入方式构成的循环依赖,对于setter注入造成的依赖是通过Spring容器提前暴露刚完成的构造器注入但未完成其他步骤的bean来完成的,而且只能解决单例作用域的bean循环依赖。通过提前暴露一个单例工厂方法,从而使得其他bean能引用到该bean.
1)Spring容器创建单例"testA"bean,首先根据无参构造器创建bean,并暴露一个ObjectFactory用于返回一个提前暴露一个创建中的bean,并将testA标识符放到"当前创建bean池",然后进行setter注入"testB";
2)Spring容器创建单例“testB”bean,首先根据无参构造器创建bean,并暴露一个"ObjectFactory"用于返货一个提前暴露一个创建中的bean,并将"testB"标识符放到"当前创建bean池",然后进行setter注入"circle".
3)Spring容器创建单例“testC” bean,首先根据无参构造器创建bean,并暴露一个ObjectFactory用于返回一个提前暴露一个创建中的bean,并将testC标识符放到“当前创建bean池”,然后进行setter注入testA,进行注入testA时由于提前暴露了ObjectFactory工厂,从而使用它返回提前暴露一个创建中的bean.
4)最后在依赖注入testB和testA完成setter注入
3、prototype范围的依赖处理
对于prototype作用域bean,Spring容器无法完成依赖注入,因为Spring容器不进行缓存prototype作用域的bean,因此无法提前暴露一个创建中的bean.
对于singleton作用域bean,可以通过setAllowCircularReferencess(false)来禁止循环引用。
五、创建bean
1 /** 2 * Actually create the specified bean. Pre-creation processing has already happened3 * at this point, e.g. checking {@codepostProcessBeforeInstantiation} callbacks.4 * <p>Differentiates between default bean instantiation, use of a5 * factory method, and autowiring a constructor.6 *@parambeanName the name of the bean7 *@parammbd the merged bean definition for the bean8 *@paramargs explicit arguments to use for constructor or factory method invocation9 *@returna new instance of the bean10 *@throwsBeanCreationException if the bean could not be created11 *@see#instantiateBean12 *@see#instantiateUsingFactoryMethod13 *@see#autowireConstructor14 */ 15 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, finalObject[] args)16 throwsBeanCreationException {17 18 //Instantiate the bean. 19 BeanWrapper instanceWrapper = null;20 if(mbd.isSingleton()) {21 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);22 }23 if (instanceWrapper == null) {24 //根据指定bean使用对应的策略创建新的实例,如:工厂方法,构造函数自动注入,简单初始化 25 instanceWrapper =createBeanInstance(beanName, mbd, args);26 }27 final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);28 Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);29 mbd.resolvedTargetType =beanType;30 31 //Allow post-processors to modify the merged bean definition. 32 synchronized(mbd.postProcessingLock) {33 if (!mbd.postProcessed) {34 try{35 //应用MergedBeanDefinitionPostProcessor applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 36 }37 catch(Throwable ex) {38 throw newBeanCreationException(mbd.getResourceDescription(), beanName,39 "Post-processing of merged bean definition failed", ex);40 }41 mbd.postProcessed = true;42 }43 }44 45 //Eagerly cache singletons to be able to resolve circular references46 //even when triggered by lifecycle interfaces like BeanFactoryAware.47 //是否需要提早曝光:单例&允许循环依赖&当前bean正在创建中。检查循环依赖 48 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && 49 isSingletonCurrentlyInCreation(beanName));50 if(earlySingletonExposure) {51 if(logger.isDebugEnabled()) {52 logger.debug("Eagerly caching bean '" + beanName + 53 "' to allow for resolving potential circular references");54 }55 //为避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory加入工厂 56 addSingletonFactory(beanName, new ObjectFactory<Object>() {57 @Override58 public Object getObject() throwsBeansException {59 //对bean再一次依赖引用,注意应用SmartInstantiationAware BeanPostProcessor.60 //其中我们熟知的AOP就是在这里将Advice动态植入bean中,若没有则直接返回bean,不做任何处理 61 returngetEarlyBeanReference(beanName, mbd, bean);62 }63 });64 }65 66 //Initialize the bean instance. 67 Object exposedObject =bean;68 try{69 //对bean进行填充,将各个属性值注入,其中可能存在依赖于其他bean的属性,则会递归初始依赖bean 70 populateBean(beanName, mbd, instanceWrapper);71 if (exposedObject != null) {72 //调用初始化方法,比如init-method 73 exposedObject =initializeBean(beanName, exposedObject, mbd);74 }75 }76 catch(Throwable ex) {77 if (ex instanceof BeanCreationException &&beanName.equals(((BeanCreationException) ex).getBeanName())) {78 throw(BeanCreationException) ex;79 }80 else{81 throw newBeanCreationException(82 mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);83 }84 }85 86 if(earlySingletonExposure) {87 Object earlySingletonReference = getSingleton(beanName, false);88 //earlySingletonReference 只有在检测到有循环依赖的情况下才会不为空 89 if (earlySingletonReference != null) {90 //如果exposedObject没有在初始化方法中被改变,也就是没有被增强 91 if (exposedObject ==bean) {92 exposedObject =earlySingletonReference;93 }94 else if (!this.allowRawInjectionDespiteWrapping &&hasDependentBean(beanName)) {95 String[] dependentBeans =getDependentBeans(beanName);96 Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);97 //检测依赖 98 for(String dependentBean : dependentBeans) {99 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {100 actualDependentBeans.add(dependentBean);101 }102 }103 //因为bean创建后其所依赖的bean一定是已经创建的,actualDependentBeans不为空则表示当前bean创建后其依赖的bean却没有全部创建完,也就是说存在依赖循环 104 if (!actualDependentBeans.isEmpty()) {105 throw newBeanCurrentlyInCreationException(beanName,106 "Bean with name '" + beanName + "' has been injected into other beans [" + 107 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + 108 "] in its raw version as part of a circular reference, but has eventually been " + 109 "wrapped. This means that said other beans do not use the final version of the " + 110 "bean. This is often the result of over-eager type matching - consider using " + 111 "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");112 }113 }114 }115 }116 117 //Register bean as disposable. 118 try{119 //根据scopse注册bean 120 registerDisposableBeanIfNecessary(beanName, bean, mbd);121 }122 catch(BeanDefinitionValidationException ex) {123 throw newBeanCreationException(124 mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);125 }126 127 returnexposedObject;128 }
1、如果是单例则需要首先清楚缓存
2、实例化bean,将BeanDefinition转换为BeanWrapper
1)如果存在工厂方法则使用工厂方法进行初始化
1 /** 2 * Create a new instance for the specified bean, using an appropriate instantiation strategy:3 * factory method, constructor autowiring, or simple instantiation.4 *@parambeanName the name of the bean5 *@parammbd the bean definition for the bean6 *@paramargs explicit arguments to use for constructor or factory method invocation7 *@returnBeanWrapper for the new instance8 *@see#instantiateUsingFactoryMethod9 *@see#autowireConstructor10 *@see#instantiateBean11 */ 12 protectedBeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {13 //Make sure bean class is actually resolved at this point.14 //解析class 15 Class<?> beanClass =resolveBeanClass(mbd, beanName);16 17 if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {18 throw newBeanCreationException(mbd.getResourceDescription(), beanName,19 "Bean class isn't public, and non-public access not allowed: " +beanClass.getName());20 }21 //如果工厂方法不为空则使用工厂方法初始化策略 22 if (mbd.getFactoryMethodName() != null) {23 returninstantiateUsingFactoryMethod(beanName, mbd, args);24 }25 26 //Shortcut when re-creating the same bean... 27 boolean resolved = false;28 boolean autowireNecessary = false;29 if (args == null) {30 synchronized(mbd.constructorArgumentLock) {31 //一个类有多个构造函数,每个构造函数都有不同的参数,所以调用前需要先根据参数锁定构造函数或对应的工厂方法 32 if (mbd.resolvedConstructorOrFactoryMethod != null) {33 resolved = true;34 autowireNecessary =mbd.constructorArgumentsResolved;35 }36 }37 }38 //如果已经解析过则使用解析好的构造函数方法不需要再次锁定 39 if(resolved) {40 if(autowireNecessary) {41 //构造函数自动注入 42 return autowireConstructor(beanName, mbd, null, null);43 }44 else{45 //使用默认构造函数构造 46 returninstantiateBean(beanName, mbd);47 }48 }49 50 //Need to determine the constructor...51 //需要根据参数解析构造函数 52 Constructor<?>[] ctors =determineConstructorsFromBeanPostProcessors(beanClass, beanName);53 if (ctors != null || 54 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || 55 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {56 //构造函数自动注入 57 returnautowireConstructor(beanName, mbd, ctors, args);58 }59 60 //No special handling: simply use no-arg constructor.61 //使用默认构造函数构造 62 returninstantiateBean(beanName, mbd);63 }
- 如果在RootBeanDefinition中存在factoryMethodName属性,或者说在配置文件中配置了factory-method那么Spring会尝试使用instantiateUsingFactoryMethod(beanName,mbd,args)方法根据RootBeanDefinition中的配置生产bean的实例。
- 解析构造函数并进行构造函数的实例化,因为一个bean对应的类中可能会有多个构造函数,而每个构造函数的参数不同,Spring在根据参数及类型去判断最终会使用哪个构造函数进行实例化。但是判断的过程是个比较消耗性能的步骤,所以采用缓存机制,如果已经解析过则不需要重复解析而是直接从RootBeanDefinition中的属性resolveConstructorOrFactoryMethod缓存的值去取,否则需要再次解析,并将解析的结果添加至RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod中。
2)一个类有多个构造函数,每个构造函数都有不同的参数,所以需要根据参数锁定构造函数并进行初始化
1 /** 2 * "autowire constructor" (with constructor arguments by type) behavior.3 * Also applied if explicit constructor argument values are specified,4 * matching all remaining arguments with beans from the bean factory.5 * <p>This corresponds to constructor injection: In this mode, a Spring6 * bean factory is able to host components that expect constructor-based7 * dependency resolution.8 *@parambeanName the name of the bean9 *@parammbd the merged bean definition for the bean10 *@paramchosenCtors chosen candidate constructors (or {@codenull} if none)11 *@paramexplicitArgs argument values passed in programmatically via the getBean method,12 * or {@codenull} if none (-> use constructor argument values from bean definition)13 *@returna BeanWrapper for the new instance14 */ 15 public BeanWrapper autowireConstructor(final String beanName, finalRootBeanDefinition mbd,16 Constructor<?>[] chosenCtors, finalObject[] explicitArgs) {17 18 BeanWrapperImpl bw = newBeanWrapperImpl();19 this.beanFactory.initBeanWrapper(bw);20 21 Constructor<?> constructorToUse = null;22 ArgumentsHolder argsHolderToUse = null;23 Object[] argsToUse = null;24 //explicitArgs通过getBean方法传入25 //如果getBean方法调用的时候指定方法参数那么直接使用 26 if (explicitArgs != null) {27 argsToUse =explicitArgs;28 }29 else{30 //如果在getBean方法时候没有指定则尝试从配置文件中解析 31 Object[] argsToResolve = null;32 //尝试从缓存中获取 33 synchronized(mbd.constructorArgumentLock) {34 constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;35 if (constructorToUse != null &&mbd.constructorArgumentsResolved) {36 //Found a cached constructor...37 //从缓存中取 38 argsToUse =mbd.resolvedConstructorArguments;39 if (argsToUse == null) {40 //配置的构造函数参数 41 argsToResolve =mbd.preparedConstructorArguments;42 }43 }44 }45 //如果缓存中存在 46 if (argsToResolve != null) {47 //解析参数类型,如给定方法的构造函数A(int,int)则通过此方法后就会把配置中的("1","1")转换为(1,1)48 //缓存中的值可能是原始值也可能是最终值 49 argsToUse =resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);50 }51 }52 //没有被缓存 53 if (constructorToUse == null) {54 //Need to resolve the constructor. 55 boolean autowiring = (chosenCtors != null || 56 mbd.getResolvedAutowireMode() ==RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);57 ConstructorArgumentValues resolvedValues = null;58 59 intminNrOfArgs;60 if (explicitArgs != null) {61 minNrOfArgs =explicitArgs.length;62 }63 else{64 //提取配置文件中的配置的构造函数参数 65 ConstructorArgumentValues cargs =mbd.getConstructorArgumentValues();66 //用于承载解析后的构造函数参数的值 67 resolvedValues = newConstructorArgumentValues();68 //能解析到的参数个数 69 minNrOfArgs =resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);70 }71 72 //Take specified constructors, if any. 73 Constructor<?>[] candidates =chosenCtors;74 if (candidates == null) {75 Class<?> beanClass =mbd.getBeanClass();76 try{77 candidates = (mbd.isNonPublicAccessAllowed() ? 78 beanClass.getDeclaredConstructors() : beanClass.getConstructors());79 }80 catch(Throwable ex) {81 throw newBeanCreationException(mbd.getResourceDescription(), beanName,82 "Resolution of declared constructors on bean Class [" + beanClass.getName() + 83 "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);84 }85 }86 //排序给定的构造函数,public构造函数优先参数数量降序、非public构造函数参数数量降序 87 AutowireUtils.sortConstructors(candidates);88 int minTypeDiffWeight =Integer.MAX_VALUE;89 Set<Constructor<?>> ambiguousConstructors = null;90 LinkedList<UnsatisfiedDependencyException> causes = null;91 92 for (Constructor<?>candidate : candidates) {93 Class<?>[] paramTypes =candidate.getParameterTypes();94 95 if (constructorToUse != null && argsToUse.length >paramTypes.length) {96 //如果已经找到选用的构造函数或者需要的参数个数小于当前的构造函数参数个数则终止,因为已经按照参数个数降序排列97 //Already found greedy constructor that can be satisfied ->98 //do not look any further, there are only less greedy constructors left. 99 break;100 }101 if (paramTypes.length <minNrOfArgs) {102 //参数个数不相等 103 continue;104 }105 106 ArgumentsHolder argsHolder;107 if (resolvedValues != null) {108 //有参数则根据值构造对应参数类型的参数 109 try{110 String[] paramNames =ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);111 if (paramNames == null) {112 //获取参数名称探索器 113 ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();114 if (pnd != null) {115 //获取指定构造函数的参数名称 116 paramNames =pnd.getParameterNames(candidate);117 }118 }119 //根据名称和数据类型创建参数持有者 120 argsHolder =createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,121 getUserDeclaredConstructor(candidate), autowiring);122 }123 catch(UnsatisfiedDependencyException ex) {124 if (this.beanFactory.logger.isTraceEnabled()) {125 this.beanFactory.logger.trace(126 "Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " +ex);127 }128 //Swallow and try next constructor. 129 if (causes == null) {130 causes = new LinkedList<UnsatisfiedDependencyException>();131 }132 causes.add(ex);133 continue;134 }135 }136 else{137 //Explicit arguments given -> arguments length must match exactly. 138 if (paramTypes.length !=explicitArgs.length) {139 continue;140 }141 //构造函数没有参数的情况 142 argsHolder = newArgumentsHolder(explicitArgs);143 }144 //探测是否有不确定性的构造函数存在,例如不同构造函数的参数为父子关系 145 int typeDiffWeight = (mbd.isLenientConstructorResolution() ? 146 argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));147 //Choose this constructor if it represents the closest match.148 //如果它代表着当前最接近的匹配则选择作为构造函数 149 if (typeDiffWeight <minTypeDiffWeight) {150 constructorToUse =candidate;151 argsHolderToUse =argsHolder;152 argsToUse =argsHolder.arguments;153 minTypeDiffWeight =typeDiffWeight;154 ambiguousConstructors = null;155 }156 else if (constructorToUse != null && typeDiffWeight ==minTypeDiffWeight) {157 if (ambiguousConstructors == null) {158 ambiguousConstructors = new LinkedHashSet<Constructor<?>>();159 ambiguousConstructors.add(constructorToUse);160 }161 ambiguousConstructors.add(candidate);162 }163 }164 165 if (constructorToUse == null) {166 if (causes != null) {167 UnsatisfiedDependencyException ex =causes.removeLast();168 for(Exception cause : causes) {169 this.beanFactory.onSuppressedException(cause);170 }171 throwex;172 }173 throw newBeanCreationException(mbd.getResourceDescription(), beanName,174 "Could not resolve matching constructor " + 175 "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");176 }177 else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {178 throw newBeanCreationException(mbd.getResourceDescription(), beanName,179 "Ambiguous constructor matches found in bean '" + beanName + "' " + 180 "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " + 181 ambiguousConstructors);182 }183 184 if (explicitArgs == null) {185 //将解析的构造函数加入缓存 186 argsHolderToUse.storeCache(mbd, constructorToUse);187 }188 }189 190 try{191 Object beanInstance;192 193 if (System.getSecurityManager() != null) {194 final Constructor<?> ctorToUse =constructorToUse;195 final Object[] argumentsToUse =argsToUse;196 beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {197 @Override198 publicObject run() {199 returnbeanFactory.getInstantiationStrategy().instantiate(200 mbd, beanName, beanFactory, ctorToUse, argumentsToUse);201 }202 }, beanFactory.getAccessControlContext());203 }204 else{205 beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(206 mbd, beanName, this.beanFactory, constructorToUse, argsToUse);207 }208 //将构建的实例加入BeanWrapper中 209 bw.setBeanInstance(beanInstance);210 returnbw;211 }212 catch(Throwable ex) {213 throw newBeanCreationException(mbd.getResourceDescription(), beanName,214 "Bean instantiation via constructor failed", ex);215 }216 }
3)如果既不存在工厂方法也不存在带有参数的构造函数,则使用默认的构造函数进行bean的实例化
1 /** 2 * Instantiate the given bean using its default constructor.3 *@parambeanName the name of the bean4 *@parammbd the bean definition for the bean5 *@returnBeanWrapper for the new instance6 * 不带参数的构造函数的实例化过程7 */ 8 protected BeanWrapper instantiateBean(final String beanName, finalRootBeanDefinition mbd) {9 try{10 Object beanInstance;11 final BeanFactory parent = this;12 if (System.getSecurityManager() != null) {13 beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {14 @Override15 publicObject run() {16 returngetInstantiationStrategy().instantiate(mbd, beanName, parent);17 }18 }, getAccessControlContext());19 }20 else{21 beanInstance =getInstantiationStrategy().instantiate(mbd, beanName, parent);22 }23 BeanWrapper bw = newBeanWrapperImpl(beanInstance);24 initBeanWrapper(bw);25 returnbw;26 }27 catch(Throwable ex) {28 throw newBeanCreationException(29 mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);30 }31 }
1 //实例化策略 2 @Override3 publicObject instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {4 //Don't override the class with CGLIB if no overrides.5 //如果有需要覆盖或者动态替换的方法则当然需要使用cglib进行动态代理,因为可以在创建代理的同时将动态方法织入类中6 //但是如果没有需要动态改变的方法,为了方便直接反射就可以了 7 if(bd.getMethodOverrides().isEmpty()) {8 Constructor<?>constructorToUse;9 synchronized(bd.constructorArgumentLock) {10 constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;11 if (constructorToUse == null) {12 final Class<?> clazz =bd.getBeanClass();13 if(clazz.isInterface()) {14 throw new BeanInstantiationException(clazz, "Specified class is an interface");15 }16 try{17 if (System.getSecurityManager() != null) {18 constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {19 @Override20 public Constructor<?> run() throwsException {21 return clazz.getDeclaredConstructor((Class[]) null);22 }23 });24 }25 else{26 constructorToUse = clazz.getDeclaredConstructor((Class[]) null);27 }28 bd.resolvedConstructorOrFactoryMethod =constructorToUse;29 }30 catch(Throwable ex) {31 throw new BeanInstantiationException(clazz, "No default constructor found", ex);32 }33 }34 }35 returnBeanUtils.instantiateClass(constructorToUse);36 }37 else{38 //Must generate CGLIB subclass. 39 returninstantiateWithMethodInjection(bd, beanName, owner);40 }41 }
3)MergedBeanDefinitionPostProcessor的应用
bean合并后的处理,Autowired注解正是通过此方法实现注入类型的预解析
4)依赖处理
在Spring中会有循环依赖额情况,例如,当A中含有B的属性,而B中又含有A的属性时就会构成一个循环依赖,此时如果A和B都是单例,那么在Spring中的处理方式就是当创建B的时候,涉及自动注入A的步骤时,并不是直接去再次创建A,而是通过放入缓存中的ObjectFactory来创建实例,这样就解决了循环依赖的问题。
5)属性填充,将所有属性填充至bean的实例中
1 /** 2 * Populate the bean instance in the given BeanWrapper with the property values3 * from the bean definition.4 *@parambeanName the name of the bean5 *@parammbd the bean definition for the bean6 *@parambw BeanWrapper with bean instance7 */ 8 protected voidpopulateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {9 PropertyValues pvs =mbd.getPropertyValues();10 11 if (bw == null) {12 if (!pvs.isEmpty()) {13 throw newBeanCreationException(14 mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");15 }16 else{17 //Skip property population phase for null instance.18 //没有可填充的属性 19 return;20 }21 }22 23 //Give any InstantiationAwareBeanPostProcessors the opportunity to modify the24 //state of the bean before properties are set. This can be used, for example,25 //to support styles of field injection.26 //给InstantiationAwareBeanPostProcessors最后一次机会在属性设置前来改变bean.27 //如:可以用来支撑属性注入的类型 28 boolean continueWithPropertyPopulation = true;29 30 if (!mbd.isSynthetic() &&hasInstantiationAwareBeanPostProcessors()) {31 for(BeanPostProcessor bp : getBeanPostProcessors()) {32 if (bp instanceofInstantiationAwareBeanPostProcessor) {33 InstantiationAwareBeanPostProcessor ibp =(InstantiationAwareBeanPostProcessor) bp;34 //返回值为是否继续填充bean 35 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {36 continueWithPropertyPopulation = false;37 break;38 }39 }40 }41 }42 //如果后处理器发出停止填充命令则终止后续的执行 43 if (!continueWithPropertyPopulation) {44 return;45 }46 47 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || 48 mbd.getResolvedAutowireMode() ==RootBeanDefinition.AUTOWIRE_BY_TYPE) {49 MutablePropertyValues newPvs = newMutablePropertyValues(pvs);50 51 //Add property values based on autowire by name if applicable.52 //根据名称自动注入 53 if (mbd.getResolvedAutowireMode() ==RootBeanDefinition.AUTOWIRE_BY_NAME) {54 autowireByName(beanName, mbd, bw, newPvs);55 }56 57 //Add property values based on autowire by type if applicable.58 //根据类型自动注入 59 if (mbd.getResolvedAutowireMode() ==RootBeanDefinition.AUTOWIRE_BY_TYPE) {60 autowireByType(beanName, mbd, bw, newPvs);61 }62 63 pvs =newPvs;64 }65 //后处理器已经初始化 66 boolean hasInstAwareBpps =hasInstantiationAwareBeanPostProcessors();67 //需要依赖检查 68 boolean needsDepCheck = (mbd.getDependencyCheck() !=RootBeanDefinition.DEPENDENCY_CHECK_NONE);69 70 if (hasInstAwareBpps ||needsDepCheck) {71 PropertyDescriptor[] filteredPds =filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);72 if(hasInstAwareBpps) {73 for(BeanPostProcessor bp : getBeanPostProcessors()) {74 if (bp instanceofInstantiationAwareBeanPostProcessor) {75 InstantiationAwareBeanPostProcessor ibp =(InstantiationAwareBeanPostProcessor) bp;76 //对所有需要依赖检查的属性进行后处理 77 pvs =ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);78 if (pvs == null) {79 return;80 }81 }82 }83 }84 if(needsDepCheck) {85 //依赖检查,对应depends-on属性 86 checkDependencies(beanName, mbd, filteredPds, pvs);87 }88 }89 //将属性应用到bean中 90 applyPropertyValues(beanName, mbd, bw, pvs);91 }
- InstantiationAwareBeanPostProcessor处理器的postProcessAfterInstantitation函数的应用,此函数可以控制程序是否继续进行属性填充
- 根据注入类型(byName/byType)提取依赖的bean,并统一存入PropertyValues中
- autoWireByName
1 /** 2 * Fill in any missing property values with references to3 * other beans in this factory if autowire is set to "byName".4 *@parambeanName the name of the bean we're wiring up.5 * Useful for debugging messages; not used functionally.6 *@parammbd bean definition to update through autowiring7 *@parambw BeanWrapper from which we can obtain information about the bean8 *@parampvs the PropertyValues to register wired objects with9 */ 10 protected voidautowireByName(11 String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {12 //寻找bw中需要依赖注入的属性 13 String[] propertyNames =unsatisfiedNonSimpleProperties(mbd, bw);14 for(String propertyName : propertyNames) {15 if(containsBean(propertyName)) {16 //递归初始化相关的bean 17 Object bean =getBean(propertyName);18 pvs.add(propertyName, bean);19 //注册依赖 20 registerDependentBean(propertyName, beanName);21 if(logger.isDebugEnabled()) {22 logger.debug("Added autowiring by name from bean name '" + beanName + 23 "' via property '" + propertyName + "' to bean named '" + propertyName + "'");24 }25 }26 else{27 if(logger.isTraceEnabled()) {28 logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName + 29 "' by name: no matching bean found");30 }31 }32 }33 }
- autowireByType
1 /** 2 * Abstract method defining "autowire by type" (bean properties by type) behavior.3 * <p>This is like PicoContainer default, in which there must be exactly one bean4 * of the property type in the bean factory. This makes bean factories simple to5 * configure for small namespaces, but doesn't work as well as standard Spring6 * behavior for bigger applications.7 *@parambeanName the name of the bean to autowire by type8 *@parammbd the merged bean definition to update through autowiring9 *@parambw BeanWrapper from which we can obtain information about the bean10 *@parampvs the PropertyValues to register wired objects with11 */ 12 protected voidautowireByType(13 String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {14 15 TypeConverter converter =getCustomTypeConverter();16 if (converter == null) {17 converter =bw;18 }19 20 Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);21 //寻找bw中需要依赖注入的属性 22 String[] propertyNames =unsatisfiedNonSimpleProperties(mbd, bw);23 for(String propertyName : propertyNames) {24 try{25 PropertyDescriptor pd =bw.getPropertyDescriptor(propertyName);26 //Don't try autowiring by type for type Object: never makes sense,27 //even if it technically is a unsatisfied, non-simple property. 28 if (Object.class !=pd.getPropertyType()) {29 //探测指定属性的set方法 30 MethodParameter methodParam =BeanUtils.getWriteMethodParameter(pd);31 //Do not allow eager init for type matching in case of a prioritized post-processor. 32 boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());33 DependencyDescriptor desc = newAutowireByTypeDependencyDescriptor(methodParam, eager);34 //解析指定beanName的属性所匹配的值,并把解析到的属性名称存储在autowireBeanNames中,当属性存在多个封装bean时 35 Object autowiredArgument =resolveDependency(desc, beanName, autowiredBeanNames, converter);36 if (autowiredArgument != null) {37 pvs.add(propertyName, autowiredArgument);38 }39 for(String autowiredBeanName : autowiredBeanNames) {40 //注册依赖 registerDependentBean(autowiredBeanName, beanName); 41 if(logger.isDebugEnabled()) {42 logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" + 43 propertyName + "' to bean named '" + autowiredBeanName + "'");44 }45 }46 autowiredBeanNames.clear();47 }48 }49 catch(BeansException ex) {50 throw newUnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);51 }52 }53 }
- 寻找类型匹配的逻辑实现封装resolveDependency
1 @Override2 publicObject resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,3 Set<String> autowiredBeanNames, TypeConverter typeConverter) throwsBeansException {4 5 descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());6 if (javaUtilOptionalClass ==descriptor.getDependencyType()) {7 return newOptionalDependencyFactory().createOptionalDependency(descriptor, requestingBeanName);8 }9 else if (ObjectFactory.class == descriptor.getDependencyType() || 10 ObjectProvider.class ==descriptor.getDependencyType()) {11 return newDependencyObjectProvider(descriptor, requestingBeanName);12 }13 else if (javaxInjectProviderClass ==descriptor.getDependencyType()) {14 return newJsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);15 }16 else{17 Object result =getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(18 descriptor, requestingBeanName);19 if (result == null) {20 result =doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);21 }22 returnresult;23 }24 }25 26 publicObject doResolveDependency(DependencyDescriptor descriptor, String beanName,27 Set<String> autowiredBeanNames, TypeConverter typeConverter) throwsBeansException {28 29 InjectionPoint previousInjectionPoint =ConstructorResolver.setCurrentInjectionPoint(descriptor);30 try{31 Object shortcut = descriptor.resolveShortcut(this);32 if (shortcut != null) {33 returnshortcut;34 }35 36 Class<?> type =descriptor.getDependencyType();37 Object value =getAutowireCandidateResolver().getSuggestedValue(descriptor);38 if (value != null) {39 if (value instanceofString) {40 String strVal =resolveEmbeddedValue((String) value);41 BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);42 value =evaluateBeanDefinitionString(strVal, bd);43 }44 TypeConverter converter = (typeConverter != null ?typeConverter : getTypeConverter());45 return (descriptor.getField() != null ? 46 converter.convertIfNecessary(value, type, descriptor.getField()) :47 converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));48 }49 50 Object multipleBeans =resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);51 if (multipleBeans != null) {52 returnmultipleBeans;53 }54 55 Map<String, Object> matchingBeans =findAutowireCandidates(beanName, type, descriptor);56 if(matchingBeans.isEmpty()) {57 if(isRequired(descriptor)) {58 raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);59 }60 return null;61 }62 63 String autowiredBeanName;64 Object instanceCandidate;65 66 if (matchingBeans.size() > 1) {67 autowiredBeanName =determineAutowireCandidate(matchingBeans, descriptor);68 if (autowiredBeanName == null) {69 if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {70 returndescriptor.resolveNotUnique(type, matchingBeans);71 }72 else{73 //In case of an optional Collection/Map, silently ignore a non-unique case:74 //possibly it was meant to be an empty collection of multiple regular beans75 //(before 4.3 in particular when we didn't even look for collection beans). 76 return null;77 }78 }79 instanceCandidate =matchingBeans.get(autowiredBeanName);80 }81 else{82 //We have exactly one match. 83 Map.Entry<String, Object> entry =matchingBeans.entrySet().iterator().next();84 autowiredBeanName =entry.getKey();85 instanceCandidate =entry.getValue();86 }87 88 if (autowiredBeanNames != null) {89 autowiredBeanNames.add(autowiredBeanName);90 }91 return (instanceCandidate instanceof Class ? 92 descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);93 }94 finally{95 ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);96 }97 }
- 应用InstantiationAwareBeanPostProcessor处理器的postProcessPropertyValues方法,对属性获取完毕填充前对属性的再次处理,典型应用是RequiredAnnotationBeanPostProcessor类中对属性的验证
- 将所有PropertyValues中的属性填充至BeanWrapper中
6)循环依赖检查
Spring中循环依赖只对单例有效,而对于prototype的bean,Spring没有好的解决办法,唯一要做的就是抛出异常,在这个步骤里会检测已经加载的bean是否已经出现了依赖循环,并判断是否需要抛出异常。
7)注册DisposableBean
如果配置了destory-method这里需要注册以便于在销毁时调用
8)完成创建并返回
转载于:https://www.cnblogs.com/dream-to-pku/p/7598057.html
【Spring源码分析系列】bean的加载相关推荐
- Spring源码分析系列——bean创建过程分析(三)——工厂方法创建bean
前言 spring创建bean的方式 测试代码准备 createBeanInstance()方法分析 instantiateUsingFactoryMethod()方法分析 总结 spring创建be ...
- Spring Ioc源码分析 之 Bean的加载(6):属性填充(populateBean())
"属性填充",也是在populateBean()方法中. 首先回顾下CreateBean的主流程: 如果是单例模式,从factoryBeanInstanceCache 缓存中获取B ...
- Spring源码分析系列-Bean的生命周期(总结篇)
ApplicationContext和BeanFactory BeanFactory是Spring中的顶层接口,只负责管理bean,而ApplicationContext也实现了BeanFacto ...
- Spring Ioc源码分析 之 Bean的加载(7):初始化
接着分析doCreateBean()的第6步--初始化 bean 实例对象 首先回顾下CreateBean的主流程: 如果是单例模式,从factoryBeanInstanceCache 缓存中获取Be ...
- Spring Ioc源码分析 之 Bean的加载(4):实例化Bean(createBeanInstance()方法)
实例化 Bean 在doCreateBean()代码 <2> 处,有一行代码instanceWrapper = createBeanInstance(beanName, mbd, args ...
- Spring Ioc源码分析 之 Bean的加载(5):循环依赖处理(populateBean())
首先回顾下Bean加载的主流程: 1.如果是单例模式,从factoryBeanInstanceCache 缓存中获取BeanWrapper 实例对象并删除缓存 2.调用 createBeanInsta ...
- Spring源码分析之Bean的创建过程详解
前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...
- 【Spring源码分析】Bean加载流程概览
代码入口 之前写文章都会啰啰嗦嗦一大堆再开始,进入[Spring源码分析]这个板块就直接切入正题了. 很多朋友可能想看Spring源码,但是不知道应当如何入手去看,这个可以理解:Java开发者通常从事 ...
- beaninfo详解源码解析 java_【Spring源码分析】Bean加载流程概览
代码入口 之前写文章都会啰啰嗦嗦一大堆再开始,进入[Spring源码分析]这个板块就直接切入正题了. 很多朋友可能想看Spring源码,但是不知道应当如何入手去看,这个可以理解:Java开发者通常从事 ...
最新文章
- 为什么要把html改为jsp,为什么要用ZHTML替换JSP
- Kamailio v4.4.6 发布,开源 SIP 服务器
- android屏幕适配的目的,Android 不同分辨率下屏幕适配的实战方案与经验总结
- mySql存储过程,简单实现实例
- 升级总代分享思路_桃生企业至尊七郎瓷砖新展厅全新升级惊艳亮相
- layui html模块化,终于搞懂了layui的模块化
- python初体验-hello world答案_Python初体验_基础(一)
- s3cmd安装及使用
- asp2.0 GridView OnRowDataBound event
- 手机上什么App能连接mysql_这款APP让你的手机瞬间变身服务器,php+mysql,太硬核了!...
- cocos creator 加载微信云端图片
- windows微信双开
- 批处理 bat cmd 命令大全
- 目标检测的Tricks | 【Trick13】使用kmeans与遗传算法聚类anchor
- SpringBoot 项目中在Controller 直接调用Mapper,提示:Field mapper in ‘*Controller ‘ required a bean of type ‘*Map
- 天猫,淘宝,京东收货信息中,自动识别手机号、姓名、省市区
- 静态库与动态库(共享库)的联系与区别
- pandas中的.astype()使用规范问题——以.astype(int)的一种str类型数据转int类型数据报错为例
- C# DateTime Subtract
- 如何提高自己的编程能力
热门文章
- c#:Reflector+Reflexil 修改编译后的dll/exe文件
- java基础学习总结——接口
- python打印出指定目录下的所有文件夹和文件名(递归实现)
- ab压力测试: apr_socket_recv: Connection timed out (110)
- 手工卸载.Net写的win服务
- 【翻译】Play框架入门教程一:建立项目
- Javascript实现复选框(全选反选功能)
- 【Big Data - Hadoop - MapReduce】通过腾讯shuffle部署对shuffle过程进行详解
- 回顾Node文件路径
- C之 #pragma(二十二)