【Spring源码分析系列】bean的加载
前言
以 BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beans.xml"));为例查看bean的加载过程。
一、首先来看Spring中是如何实现的
- @Override
- public Object getBean(String name) throws BeansException {
- return getBean(name, Object.class);
- }
- @Override
- public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
- try {
- if (isSingleton(name)) {
- return doGetSingleton(name, requiredType);
- }
- else {
- return lookup(name, requiredType);
- }
- }
- catch (NameNotFoundException ex) {
- throw new NoSuchBeanDefinitionException(name, "not found in JNDI environment");
- }
- catch (TypeMismatchNamingException ex) {
- throw new BeanNotOfRequiredTypeException(name, ex.getRequiredType(), ex.getActualType());
- }
- catch (NamingException ex) {
- throw new BeanDefinitionStoreException("JNDI environment", name, "JNDI lookup failed", ex);
- }
- }
- //检查要加载的bean是否是单例
- @Override
- public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
- return this.shareableResources.contains(name);
- }
- //如果是单例的话从单例的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) throws NamingException {
- synchronized (this.singletonObjects) {
- if (this.singletonObjects.containsKey(name)) {
- Object jndiObject = this.singletonObjects.get(name);
- if (requiredType != null && !requiredType.isInstance(jndiObject)) {
- throw new TypeMismatchNamingException(
- convertJndiName(name), requiredType, (jndiObject != null ? jndiObject.getClass() : null));
- }
- return (T) jndiObject;
- }
- T jndiObject = lookup(name, requiredType);
- this.singletonObjects.put(name, jndiObject);
- return jndiObject;
- }
- }
- //实例化Bean
- /**
- * Perform an actual JNDI lookup for the given name via the JndiTemplate.
- * <p>If the name doesn't begin with "java:comp/env/", this prefix is added
- * if "resourceRef" is set to "true".
- * @param jndiName the JNDI name to look up
- * @param requiredType the required type of the object
- * @return the obtained object
- * @throws NamingException if the JNDI lookup failed
- * @see #setResourceRef
- */
- protected <T> T lookup(String jndiName, Class<T> requiredType) throws NamingException {
- Assert.notNull(jndiName, "'jndiName' must not be null");
- String convertedName = convertJndiName(jndiName);
- T jndiObject;
- try {
- jndiObject = getJndiTemplate().lookup(convertedName, requiredType);
- }
- catch (NamingException ex) {
- if (!convertedName.equals(jndiName)) {
- // Try fallback to originally specified name...
- if (logger.isDebugEnabled()) {
- logger.debug("Converted JNDI name [" + convertedName +
- "] not found - trying original name [" + jndiName + "]. " + ex);
- }
- jndiObject = getJndiTemplate().lookup(jndiName, requiredType);
- }
- else {
- throw ex;
- }
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Located object with JNDI name [" + convertedName + "]");
- }
- return jndiObject;
- }
二、FactoryBean的使用
一般情况下,Spring通过反射机制利用bean的class属性指定实现类来实例化bean.在某些情况下,实例化bean过程比较复杂,如果按照传统的方式,则需要在<bean>中提供大量的配置信息,配置信息的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.beans.factory.FactoryBean<T>的工厂类接口,可以通过实现该接口定制实例化bean的逻辑。
FactoryBean接口对于Spring框架来说是非常重要的,Spring自身就提供了70多个FactoryBean的实现,他们影藏了一些实例化复杂bean的细节,给上层应用带来了便利。
该接口中的方法
- /*
- * Copyright 2002-2016 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.springframework.beans.factory;
- /**
- * Interface to be implemented by objects used within a {@link BeanFactory} which
- * are themselves factories for individual objects. If a bean implements this
- * interface, it is used as a factory for an object to expose, not directly as a
- * bean instance that will be exposed itself.
- *
- * <p><b>NB: A bean that implements this interface cannot be used as a normal bean.</b>
- * A FactoryBean is defined in a bean style, but the object exposed for bean
- * references ({@link #getObject()}) is always the object that it creates.
- *
- * <p>FactoryBeans can support singletons and prototypes, and can either create
- * objects lazily on demand or eagerly on startup. The {@link SmartFactoryBean}
- * interface allows for exposing more fine-grained behavioral metadata.
- *
- * <p>This interface is heavily used within the framework itself, for example for
- * the AOP {@link org.springframework.aop.framework.ProxyFactoryBean} or the
- * {@link org.springframework.jndi.JndiObjectFactoryBean}. It can be used for
- * custom components as well; however, this is only common for infrastructure code.
- *
- * <p><b>{@code FactoryBean} is a programmatic contract. Implementations are not
- * supposed to rely on annotation-driven injection or other reflective facilities.</b>
- * {@link #getObjectType()} {@link #getObject()} invocations may arrive early in
- * the bootstrap process, even ahead of any post-processor setup. If you need access
- * other beans, implement {@link BeanFactoryAware} and obtain them programmatically.
- *
- * <p>Finally, FactoryBean objects participate in the containing BeanFactory's
- * synchronization of bean creation. There is usually no need for internal
- * synchronization other than for purposes of lazy initialization within the
- * FactoryBean itself (or the like).
- *
- * @author Rod Johnson
- * @author Juergen Hoeller
- * @since 08.03.2003
- * @see org.springframework.beans.factory.BeanFactory
- * @see org.springframework.aop.framework.ProxyFactoryBean
- * @see org.springframework.jndi.JndiObjectFactoryBean
- */
- public interface FactoryBean<T> {
- /**
- *返回由FactoryBean创建的bean实例,如果isSingleton返回true则该实例会放到Spring容器中单实例缓存池中
- * Return an instance (possibly shared or independent) of the object
- * managed by this factory.
- * <p>As with a {@link BeanFactory}, this allows support for both the
- * Singleton and Prototype design pattern.
- * <p>If this FactoryBean is not fully initialized yet at the time of
- * the call (for example because it is involved in a circular reference),
- * throw a corresponding {@link FactoryBeanNotInitializedException}.
- * <p>As of Spring 2.0, FactoryBeans are allowed to return {@code null}
- * objects. The factory will consider this as normal value to be used; it
- * will not throw a FactoryBeanNotInitializedException in this case anymore.
- * FactoryBean implementations are encouraged to throw
- * FactoryBeanNotInitializedException themselves now, as appropriate.
- * @return an instance of the bean (can be {@code null})
- * @throws Exception in case of creation errors
- * @see FactoryBeanNotInitializedException
- */
- T getObject() throws Exception;
- /**
- *返回FactoryBean创建的bean类型
- * Return the type of object that this FactoryBean creates,
- * or {@code null} if not known in advance.
- * <p>This allows one to check for specific types of beans without
- * instantiating objects, for example on autowiring.
- * <p>In the case of implementations that are creating a singleton object,
- * this method should try to avoid singleton creation as far as possible;
- * it should rather estimate the type in advance.
- * For prototypes, returning a meaningful type here is advisable too.
- * <p>This method can be called <i>before</i> this FactoryBean has
- * been fully initialized. It must not rely on state created during
- * initialization; of course, it can still use such state if available.
- * <p><b>NOTE:</b> Autowiring will simply ignore FactoryBeans that return
- * {@code null} here. Therefore it is highly recommended to implement
- * this method properly, using the current state of the FactoryBean.
- * @return the type of object that this FactoryBean creates,
- * or {@code null} if not known at the time of the call
- * @see ListableBeanFactory#getBeansOfType
- */
- Class<?> getObjectType();
- /**
- *返回由FactoryBean创建的bean实例的作用域是singleton还是prototype
- * Is the object managed by this factory a singleton? That is,
- * will {@link #getObject()} always return the same object
- * (a reference that can be cached)?
- * <p><b>NOTE:</b> If a FactoryBean indicates to hold a singleton object,
- * the object returned from {@code getObject()} might get cached
- * by the owning BeanFactory. Hence, do not return {@code true}
- * unless the FactoryBean always exposes the same reference.
- * <p>The singleton status of the FactoryBean itself will generally
- * be provided by the owning BeanFactory; usually, it has to be
- * defined as singleton there.
- * <p><b>NOTE:</b> This method returning {@code false} does not
- * necessarily indicate that returned objects are independent instances.
- * An implementation of the extended {@link SmartFactoryBean} interface
- * may explicitly indicate independent instances through its
- * {@link SmartFactoryBean#isPrototype()} method. Plain {@link FactoryBean}
- * implementations which do not implement this extended interface are
- * simply assumed to always return independent instances if the
- * {@code isSingleton()} implementation returns {@code false}.
- * @return whether the exposed object is a singleton
- * @see #getObject()
- * @see SmartFactoryBean#isPrototype()
- */
- boolean isSingleton();
- }
当配置文件中<bean>的class配置的实现类是FactoryBean时,通过getbean()方法返回的不是FactoryBean本身,而是FactoryBean#getObject()方法所返回的对象,相当于FactoryBean#getObject()代理了getBean()方法。
- <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
- /**
- * Actually create the specified bean. Pre-creation processing has already happened
- * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
- * <p>Differentiates between default bean instantiation, use of a
- * factory method, and autowiring a constructor.
- * @param beanName the name of the bean
- * @param mbd the merged bean definition for the bean
- * @param args explicit arguments to use for constructor or factory method invocation
- * @return a new instance of the bean
- * @throws BeanCreationException if the bean could not be created
- * @see #instantiateBean
- * @see #instantiateUsingFactoryMethod
- * @see #autowireConstructor
- */
- protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
- throws BeanCreationException {
- // Instantiate the bean.
- BeanWrapper instanceWrapper = null;
- if (mbd.isSingleton()) {
- instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
- }
- if (instanceWrapper == null) {
- //根据指定bean使用对应的策略创建新的实例,如:工厂方法,构造函数自动注入,简单初始化
- instanceWrapper = createBeanInstance(beanName, mbd, args);
- }
- final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
- Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
- mbd.resolvedTargetType = beanType;
- // Allow post-processors to modify the merged bean definition.
- synchronized (mbd.postProcessingLock) {
- if (!mbd.postProcessed) {
- try {
- //应用MergedBeanDefinitionPostProcessor applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
- }
- catch (Throwable ex) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "Post-processing of merged bean definition failed", ex);
- }
- mbd.postProcessed = true;
- }
- }
- // Eagerly cache singletons to be able to resolve circular references
- // even when triggered by lifecycle interfaces like BeanFactoryAware.
- //是否需要提早曝光:单例&允许循环依赖&当前bean正在创建中。检查循环依赖
- 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");
- }
- //为避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory加入工厂
- addSingletonFactory(beanName, new ObjectFactory<Object>() {
- @Override
- public Object getObject() throws BeansException {
- //对bean再一次依赖引用,注意应用SmartInstantiationAware BeanPostProcessor.
- //其中我们熟知的AOP就是在这里将Advice动态植入bean中,若没有则直接返回bean,不做任何处理
- return getEarlyBeanReference(beanName, mbd, bean);
- }
- });
- }
- // Initialize the bean instance.
- Object exposedObject = bean;
- try {
- //对bean进行填充,将各个属性值注入,其中可能存在依赖于其他bean的属性,则会递归初始依赖bean
- populateBean(beanName, mbd, instanceWrapper);
- if (exposedObject != null) {
- //调用初始化方法,比如init-method
- 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);
- }
- }
- if (earlySingletonExposure) {
- Object earlySingletonReference = getSingleton(beanName, false);
- //earlySingletonReference 只有在检测到有循环依赖的情况下才会不为空
- if (earlySingletonReference != null) {
- //如果exposedObject没有在初始化方法中被改变,也就是没有被增强
- if (exposedObject == bean) {
- exposedObject = earlySingletonReference;
- }
- else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
- String[] dependentBeans = getDependentBeans(beanName);
- Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
- //检测依赖
- for (String dependentBean : dependentBeans) {
- if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
- actualDependentBeans.add(dependentBean);
- }
- }
- //因为bean创建后其所依赖的bean一定是已经创建的,actualDependentBeans不为空则表示当前bean创建后其依赖的bean却没有全部创建完,也就是说存在依赖循环
- if (!actualDependentBeans.isEmpty()) {
- throw new BeanCurrentlyInCreationException(beanName,
- "Bean with name '" + beanName + "' has been injected into other beans [" +
- StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
- "] in its raw version as part of a circular reference, but has eventually been " +
- "wrapped. This means that said other beans do not use the final version of the " +
- "bean. This is often the result of over-eager type matching - consider using " +
- "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
- }
- }
- }
- }
- // Register bean as disposable.
- try {
- //根据scopse注册bean
- registerDisposableBeanIfNecessary(beanName, bean, mbd);
- }
- catch (BeanDefinitionValidationException ex) {
- throw new BeanCreationException(
- mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
- }
- return exposedObject;
- }
1、如果是单例则需要首先清楚缓存
2、实例化bean,将BeanDefinition转换为BeanWrapper
1)如果存在工厂方法则使用工厂方法进行初始化
- /**
- * Create a new instance for the specified bean, using an appropriate instantiation strategy:
- * factory method, constructor autowiring, or simple instantiation.
- * @param beanName the name of the bean
- * @param mbd the bean definition for the bean
- * @param args explicit arguments to use for constructor or factory method invocation
- * @return BeanWrapper for the new instance
- * @see #instantiateUsingFactoryMethod
- * @see #autowireConstructor
- * @see #instantiateBean
- */
- protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
- // Make sure bean class is actually resolved at this point.
- //解析class
- Class<?> beanClass = resolveBeanClass(mbd, beanName);
- if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
- }
- //如果工厂方法不为空则使用工厂方法初始化策略
- if (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);
- }
- }
- // Need to determine the constructor...
- //需要根据参数解析构造函数
- Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
- if (ctors != null ||
- mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
- mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
- //构造函数自动注入
- return autowireConstructor(beanName, mbd, ctors, args);
- }
- // No special handling: simply use no-arg constructor.
- //使用默认构造函数构造
- return instantiateBean(beanName, mbd);
- }
- 如果在RootBeanDefinition中存在factoryMethodName属性,或者说在配置文件中配置了factory-method那么Spring会尝试使用instantiateUsingFactoryMethod(beanName,mbd,args)方法根据RootBeanDefinition中的配置生产bean的实例。
- 解析构造函数并进行构造函数的实例化,因为一个bean对应的类中可能会有多个构造函数,而每个构造函数的参数不同,Spring在根据参数及类型去判断最终会使用哪个构造函数进行实例化。但是判断的过程是个比较消耗性能的步骤,所以采用缓存机制,如果已经解析过则不需要重复解析而是直接从RootBeanDefinition中的属性resolveConstructorOrFactoryMethod缓存的值去取,否则需要再次解析,并将解析的结果添加至RootBeanDefinition中的属性resolvedConstructorOrFactoryMethod中。
2)一个类有多个构造函数,每个构造函数都有不同的参数,所以需要根据参数锁定构造函数并进行初始化
- /**
- * "autowire constructor" (with constructor arguments by type) behavior.
- * Also applied if explicit constructor argument values are specified,
- * matching all remaining arguments with beans from the bean factory.
- * <p>This corresponds to constructor injection: In this mode, a Spring
- * bean factory is able to host components that expect constructor-based
- * dependency resolution.
- * @param beanName the name of the bean
- * @param mbd the merged bean definition for the bean
- * @param chosenCtors chosen candidate constructors (or {@code null} if none)
- * @param explicitArgs argument values passed in programmatically via the getBean method,
- * or {@code null} if none (-> use constructor argument values from bean definition)
- * @return a BeanWrapper for the new instance
- */
- public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,
- Constructor<?>[] chosenCtors, final Object[] explicitArgs) {
- BeanWrapperImpl bw = new BeanWrapperImpl();
- this.beanFactory.initBeanWrapper(bw);
- Constructor<?> constructorToUse = null;
- ArgumentsHolder argsHolderToUse = null;
- Object[] argsToUse = null;
- //explicitArgs通过getBean方法传入
- //如果getBean方法调用的时候指定方法参数那么直接使用
- if (explicitArgs != null) {
- argsToUse = explicitArgs;
- }
- else {
- //如果在getBean方法时候没有指定则尝试从配置文件中解析
- Object[] argsToResolve = null;
- //尝试从缓存中获取
- synchronized (mbd.constructorArgumentLock) {
- constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
- if (constructorToUse != null && mbd.constructorArgumentsResolved) {
- // Found a cached constructor...
- //从缓存中取
- argsToUse = mbd.resolvedConstructorArguments;
- if (argsToUse == null) {
- //配置的构造函数参数
- argsToResolve = mbd.preparedConstructorArguments;
- }
- }
- }
- //如果缓存中存在
- if (argsToResolve != null) {
- //解析参数类型,如给定方法的构造函数A(int,int)则通过此方法后就会把配置中的("1","1")转换为(1,1)
- //缓存中的值可能是原始值也可能是最终值
- argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
- }
- }
- //没有被缓存
- if (constructorToUse == null) {
- // Need to resolve the constructor.
- boolean autowiring = (chosenCtors != null ||
- mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
- ConstructorArgumentValues resolvedValues = null;
- int minNrOfArgs;
- if (explicitArgs != null) {
- minNrOfArgs = explicitArgs.length;
- }
- else {
- //提取配置文件中的配置的构造函数参数
- ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
- //用于承载解析后的构造函数参数的值
- resolvedValues = new ConstructorArgumentValues();
- //能解析到的参数个数
- minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
- }
- // Take specified constructors, if any.
- Constructor<?>[] candidates = chosenCtors;
- if (candidates == null) {
- Class<?> beanClass = mbd.getBeanClass();
- try {
- candidates = (mbd.isNonPublicAccessAllowed() ?
- beanClass.getDeclaredConstructors() : beanClass.getConstructors());
- }
- catch (Throwable ex) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "Resolution of declared constructors on bean Class [" + beanClass.getName() +
- "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
- }
- }
- //排序给定的构造函数,public构造函数优先参数数量降序、非public构造函数参数数量降序
- AutowireUtils.sortConstructors(candidates);
- int minTypeDiffWeight = Integer.MAX_VALUE;
- Set<Constructor<?>> ambiguousConstructors = null;
- LinkedList<UnsatisfiedDependencyException> causes = null;
- for (Constructor<?> candidate : candidates) {
- Class<?>[] paramTypes = candidate.getParameterTypes();
- if (constructorToUse != null && argsToUse.length > paramTypes.length) {
- //如果已经找到选用的构造函数或者需要的参数个数小于当前的构造函数参数个数则终止,因为已经按照参数个数降序排列
- // Already found greedy constructor that can be satisfied ->
- // do not look any further, there are only less greedy constructors left.
- break;
- }
- if (paramTypes.length < minNrOfArgs) {
- //参数个数不相等
- continue;
- }
- ArgumentsHolder argsHolder;
- if (resolvedValues != null) {
- //有参数则根据值构造对应参数类型的参数
- try {
- String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
- if (paramNames == null) {
- //获取参数名称探索器
- ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
- if (pnd != null) {
- //获取指定构造函数的参数名称
- paramNames = pnd.getParameterNames(candidate);
- }
- }
- //根据名称和数据类型创建参数持有者
- argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
- getUserDeclaredConstructor(candidate), autowiring);
- }
- catch (UnsatisfiedDependencyException ex) {
- if (this.beanFactory.logger.isTraceEnabled()) {
- this.beanFactory.logger.trace(
- "Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
- }
- // Swallow and try next constructor.
- if (causes == null) {
- causes = new LinkedList<UnsatisfiedDependencyException>();
- }
- causes.add(ex);
- continue;
- }
- }
- else {
- // Explicit arguments given -> arguments length must match exactly.
- if (paramTypes.length != explicitArgs.length) {
- continue;
- }
- //构造函数没有参数的情况
- argsHolder = new ArgumentsHolder(explicitArgs);
- }
- //探测是否有不确定性的构造函数存在,例如不同构造函数的参数为父子关系
- int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
- argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
- // Choose this constructor if it represents the closest match.
- //如果它代表着当前最接近的匹配则选择作为构造函数
- if (typeDiffWeight < minTypeDiffWeight) {
- constructorToUse = candidate;
- argsHolderToUse = argsHolder;
- argsToUse = argsHolder.arguments;
- minTypeDiffWeight = typeDiffWeight;
- ambiguousConstructors = null;
- }
- else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
- if (ambiguousConstructors == null) {
- ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
- ambiguousConstructors.add(constructorToUse);
- }
- ambiguousConstructors.add(candidate);
- }
- }
- if (constructorToUse == null) {
- if (causes != null) {
- UnsatisfiedDependencyException ex = causes.removeLast();
- for (Exception cause : causes) {
- this.beanFactory.onSuppressedException(cause);
- }
- throw ex;
- }
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "Could not resolve matching constructor " +
- "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
- }
- else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "Ambiguous constructor matches found in bean '" + beanName + "' " +
- "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
- ambiguousConstructors);
- }
- if (explicitArgs == null) {
- //将解析的构造函数加入缓存
- argsHolderToUse.storeCache(mbd, constructorToUse);
- }
- }
- try {
- Object beanInstance;
- if (System.getSecurityManager() != null) {
- final Constructor<?> ctorToUse = constructorToUse;
- final Object[] argumentsToUse = argsToUse;
- beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
- @Override
- public Object run() {
- return beanFactory.getInstantiationStrategy().instantiate(
- mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
- }
- }, beanFactory.getAccessControlContext());
- }
- else {
- beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
- mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
- }
- //将构建的实例加入BeanWrapper中
- bw.setBeanInstance(beanInstance);
- return bw;
- }
- catch (Throwable ex) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "Bean instantiation via constructor failed", ex);
- }
- }
3)如果既不存在工厂方法也不存在带有参数的构造函数,则使用默认的构造函数进行bean的实例化
- /**
- * Instantiate the given bean using its default constructor.
- * @param beanName the name of the bean
- * @param mbd the bean definition for the bean
- * @return BeanWrapper for the new instance
- * 不带参数的构造函数的实例化过程
- */
- protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
- try {
- Object beanInstance;
- final BeanFactory parent = this;
- if (System.getSecurityManager() != null) {
- beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
- @Override
- public Object run() {
- return getInstantiationStrategy().instantiate(mbd, beanName, parent);
- }
- }, getAccessControlContext());
- }
- else {
- beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
- }
- BeanWrapper bw = new BeanWrapperImpl(beanInstance);
- initBeanWrapper(bw);
- return bw;
- }
- catch (Throwable ex) {
- throw new BeanCreationException(
- mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
- }
- }
- //实例化策略
- @Override
- public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
- // Don't override the class with CGLIB if no overrides.
- //如果有需要覆盖或者动态替换的方法则当然需要使用cglib进行动态代理,因为可以在创建代理的同时将动态方法织入类中
- //但是如果没有需要动态改变的方法,为了方便直接反射就可以了
- if (bd.getMethodOverrides().isEmpty()) {
- Constructor<?> constructorToUse;
- synchronized (bd.constructorArgumentLock) {
- constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
- if (constructorToUse == null) {
- final Class<?> clazz = bd.getBeanClass();
- if (clazz.isInterface()) {
- throw new BeanInstantiationException(clazz, "Specified class is an interface");
- }
- try {
- if (System.getSecurityManager() != null) {
- constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
- @Override
- public Constructor<?> run() throws Exception {
- return clazz.getDeclaredConstructor((Class[]) null);
- }
- });
- }
- else {
- constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
- }
- 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);
- }
- }
3)MergedBeanDefinitionPostProcessor的应用
bean合并后的处理,Autowired注解正是通过此方法实现注入类型的预解析
4)依赖处理
在Spring中会有循环依赖额情况,例如,当A中含有B的属性,而B中又含有A的属性时就会构成一个循环依赖,此时如果A和B都是单例,那么在Spring中的处理方式就是当创建B的时候,涉及自动注入A的步骤时,并不是直接去再次创建A,而是通过放入缓存中的ObjectFactory来创建实例,这样就解决了循环依赖的问题。
5)属性填充,将所有属性填充至bean的实例中
- /**
- * Populate the bean instance in the given BeanWrapper with the property values
- * from the bean definition.
- * @param beanName the name of the bean
- * @param mbd the bean definition for the bean
- * @param bw BeanWrapper with bean instance
- */
- protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
- PropertyValues pvs = mbd.getPropertyValues();
- if (bw == null) {
- if (!pvs.isEmpty()) {
- throw new BeanCreationException(
- mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
- }
- else {
- // Skip property population phase for null instance.
- //没有可填充的属性
- return;
- }
- }
- // 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最后一次机会在属性设置前来改变bean.
- //如:可以用来支撑属性注入的类型
- boolean continueWithPropertyPopulation = true;
- if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
- for (BeanPostProcessor bp : getBeanPostProcessors()) {
- if (bp instanceof InstantiationAwareBeanPostProcessor) {
- InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
- //返回值为是否继续填充bean
- if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
- continueWithPropertyPopulation = false;
- break;
- }
- }
- }
- }
- //如果后处理器发出停止填充命令则终止后续的执行
- if (!continueWithPropertyPopulation) {
- return;
- }
- 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;
- }
- //后处理器已经初始化
- 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()) {
- if (bp instanceof InstantiationAwareBeanPostProcessor) {
- InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
- //对所有需要依赖检查的属性进行后处理
- pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
- if (pvs == null) {
- return;
- }
- }
- }
- }
- if (needsDepCheck) {
- //依赖检查,对应depends-on属性
- checkDependencies(beanName, mbd, filteredPds, pvs);
- }
- }
- //将属性应用到bean中
- applyPropertyValues(beanName, mbd, bw, pvs);
- }
- InstantiationAwareBeanPostProcessor处理器的postProcessAfterInstantitation函数的应用,此函数可以控制程序是否继续进行属性填充
- 根据注入类型(byName/byType)提取依赖的bean,并统一存入PropertyValues中
- autoWireByName
- /**
- * Fill in any missing property values with references to
- * other beans in this factory if autowire is set to "byName".
- * @param beanName the name of the bean we're wiring up.
- * Useful for debugging messages; not used functionally.
- * @param mbd bean definition to update through autowiring
- * @param bw BeanWrapper from which we can obtain information about the bean
- * @param pvs the PropertyValues to register wired objects with
- */
- protected void autowireByName(
- String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
- //寻找bw中需要依赖注入的属性
- String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
- for (String propertyName : propertyNames) {
- if (containsBean(propertyName)) {
- //递归初始化相关的bean
- Object bean = getBean(propertyName);
- pvs.add(propertyName, bean);
- //注册依赖
- registerDependentBean(propertyName, beanName);
- if (logger.isDebugEnabled()) {
- logger.debug("Added autowiring by name from bean name '" + beanName +
- "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
- }
- }
- else {
- if (logger.isTraceEnabled()) {
- logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
- "' by name: no matching bean found");
- }
- }
- }
- }
- /**
- autowireByType
- /**
- * Abstract method defining "autowire by type" (bean properties by type) behavior.
- * <p>This is like PicoContainer default, in which there must be exactly one bean
- * of the property type in the bean factory. This makes bean factories simple to
- * configure for small namespaces, but doesn't work as well as standard Spring
- * behavior for bigger applications.
- * @param beanName the name of the bean to autowire by type
- * @param mbd the merged bean definition to update through autowiring
- * @param bw BeanWrapper from which we can obtain information about the bean
- * @param pvs the PropertyValues to register wired objects with
- */
- protected void autowireByType(
- String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
- TypeConverter converter = getCustomTypeConverter();
- if (converter == null) {
- converter = bw;
- }
- Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
- //寻找bw中需要依赖注入的属性
- String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
- for (String propertyName : propertyNames) {
- try {
- PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
- // Don't try autowiring by type for type Object: never makes sense,
- // even if it technically is a unsatisfied, non-simple property.
- if (Object.class != pd.getPropertyType()) {
- //探测指定属性的set方法
- MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
- // Do not allow eager init for type matching in case of a prioritized post-processor.
- boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
- DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
- //解析指定beanName的属性所匹配的值,并把解析到的属性名称存储在autowireBeanNames中,当属性存在多个封装bean时
- Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
- if (autowiredArgument != null) {
- pvs.add(propertyName, autowiredArgument);
- }
- for (String autowiredBeanName : autowiredBeanNames) {
- //注册依赖 registerDependentBean(autowiredBeanName, beanName);
- if (logger.isDebugEnabled()) {
- logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
- propertyName + "' to bean named '" + autowiredBeanName + "'");
- }
- }
- autowiredBeanNames.clear();
- }
- }
- catch (BeansException ex) {
- throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
- }
- }
- }
- /**
- 寻找类型匹配的逻辑实现封装resolveDependency
- @Override
- public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
- Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
- descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
- if (javaUtilOptionalClass == descriptor.getDependencyType()) {
- return new OptionalDependencyFactory().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 Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
- }
- else {
- Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
- descriptor, requestingBeanName);
- if (result == null) {
- result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
- }
- return result;
- }
- }
- public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
- Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
- InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
- try {
- Object shortcut = descriptor.resolveShortcut(this);
- if (shortcut != null) {
- return shortcut;
- }
- Class<?> type = descriptor.getDependencyType();
- Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
- if (value != null) {
- if (value instanceof String) {
- String strVal = resolveEmbeddedValue((String) value);
- BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
- value = evaluateBeanDefinitionString(strVal, bd);
- }
- TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
- return (descriptor.getField() != null ?
- converter.convertIfNecessary(value, type, descriptor.getField()) :
- converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
- }
- Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
- if (multipleBeans != null) {
- return multipleBeans;
- }
- Map<String, Object> 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() > 1) {
- autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
- if (autowiredBeanName == null) {
- if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
- return descriptor.resolveNotUnique(type, matchingBeans);
- }
- else {
- // In case of an optional Collection/Map, silently ignore a non-unique case:
- // possibly it was meant to be an empty collection of multiple regular beans
- // (before 4.3 in particular when we didn't even look for collection beans).
- return null;
- }
- }
- instanceCandidate = matchingBeans.get(autowiredBeanName);
- }
- else {
- // We have exactly one match.
- Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
- autowiredBeanName = entry.getKey();
- instanceCandidate = entry.getValue();
- }
- if (autowiredBeanNames != null) {
- autowiredBeanNames.add(autowiredBeanName);
- }
- return (instanceCandidate instanceof Class ?
- descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
- }
- finally {
- ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
- }
- }
- @Override
- 应用InstantiationAwareBeanPostProcessor处理器的postProcessPropertyValues方法,对属性获取完毕填充前对属性的再次处理,典型应用是RequiredAnnotationBeanPostProcessor类中对属性的验证
- 将所有PropertyValues中的属性填充至BeanWrapper中
6)循环依赖检查
Spring中循环依赖只对单例有效,而对于prototype的bean,Spring没有好的解决办法,唯一要做的就是抛出异常,在这个步骤里会检测已经加载的bean是否已经出现了依赖循环,并判断是否需要抛出异常。
7)注册DisposableBean
如果配置了destory-method这里需要注册以便于在销毁时调用
8)完成创建并返回
【Spring源码分析系列】bean的加载的更多相关文章
- Spring源码分析之Bean的加载流程
spring版本为4.3.6.RELEASE 不管是xml方式配置bean还是基于注解的形式,最终都会调用AbstractApplicationContext的refresh方法: @Override ...
- 【Spring源码分析】非懒加载的单例Bean初始化过程(下篇)
doCreateBean方法 上文[Spring源码分析]非懒加载的单例Bean初始化过程(上篇),分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的.先贴一下 ...
- 【Spring源码分析】非懒加载的单例Bean初始化前后的一些操作
前言 之前两篇文章[Spring源码分析]非懒加载的单例Bean初始化过程(上篇)和[Spring源码分析]非懒加载的单例Bean初始化过程(下篇)比较详细地分析了非懒加载的单例Bean的初始化过程, ...
- Spring源码分析:非懒加载的单例Bean初始化前后的一些操作
之前两篇文章Spring源码分析:非懒加载的单例Bean初始化过程(上)和Spring源码分析:非懒加载的单例Bean初始化过程(下)比较详细地分析了非懒加载的单例Bean的初始化过程,整个流程始于A ...
- Spring源码分析:非懒加载的单例Bean初始化过程(下)
上文Spring源码分析:非懒加载的单例Bean初始化过程(上),分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的.先贴一下AbstractAutowireC ...
- 【Spring源码分析】非懒加载的单例Bean初始化过程(上篇)
代码入口 上文[Spring源码分析]Bean加载流程概览,比较详细地分析了Spring上下文加载的代码入口,并且在AbstractApplicationContext的refresh方法中,点出了f ...
- Spring源码分析:非懒加载的单例Bean初始化过程(上)
上文[Spring源码分析]Bean加载流程概览,比较详细地分析了Spring上下文加载的代码入口,并且在AbstractApplicationContext的refresh方法中,点出了finish ...
- 【SpringBoot源码分析】-Bean的加载过程
-- 以下内容均基于2.1.8.RELEASE版本 在<SpringBoot启动过程的分析>系列文章中简要的对SpringBoot整体的启动流程作了梳理,但并未针对诸多细节进行分析.前面的 ...
- spring源码学习之bean的加载(二)
这是接着上篇继续写bean的加载过程,好像是有点太多了,因为bean的加载过程是很复杂的,要处理的情况有很多,继续... 7.创建bean 常规的bean的创建时通过doCreateBean方法来实现 ...
- spring源码学习之bean的加载(一)
对XML文件的解析基本上已经大致的走了一遍,虽然没有能吸收多少,但是脑子中总是有些印象的,接下来看下spring中的bean的加载,这个比xml解析复杂的多.这个加载,在我们使用的时候基本上是:Bea ...
随机推荐
- Java条形码插件
项目中需要用条形码插件,基于Java平台的 需要比较简单,根据一个12位的数字生成一个条形码图片即可 之前一直用Google的Zxing,因为功能强大,调用简单,网上也有很多资料 后来发现,Zxing ...
- 实现linux服务器之间无密码互访
最近老是在群里看到许多同学问,linux之间无密码互访怎么弄啊,百度的看得我头晕之类的,所以我就写写怎么样在两台linux服务器之间实现无密码互访,也就是让它们互相信任的意思,废话不多说,直接上菜. ...
- 干货分享 超炫丽的HTML5/jQuery应用及代码
今天我们要来分享一些HTML5干货,对于前段开发者来说,这些HTML5应用和jQuery插件将会让你的项目更加生动和炫丽,至少在UI设计方面,或多或少会带给你一点设计灵感,赶紧收藏和分享吧.另外这些H ...
- hibernate.cfg配置mysql方言
hibernate自动建表,mysql高版本不支持 type=InnoDB 中的type关键字. 应该使用engine关键字 而非type 所以需要在hibernate.cfg.xml中配置方言.否则 ...
- IOS_多线程
苹果的Cocoa框架支持的多线程机制有三中NSThread.GCD.NSOperation. NSThread:是官方推荐的也是最主要的线程创建方式,可是须要开发这自己去管理线程的生命周期比如线程同步 ...
- jquery获取data-xxx自定义属性的值遇到的问题
直接用jquery的 data("name") 获取 data-name的值有问题,获取的只是最初的值,即使后边改变也不会变,所以还是要用attr("data-name& ...
- 17 HTTP编程入门
http请求原理 http请求原理我就不多说了,网上一搜就能搜索到,下面我注意是记录下http模块的使用方法 http 模块 HTTP-server hello world 我们使用HandleFun ...
- ABBYY FineReader错误代码142和55
在使用ABBYY FineReader 12OCR文字识别软件创建PDF文件时,有时会出现以下错误提示:内部程序错误..\Src\SpecialFontFactory.cpp,142和内部程序错误.. ...
- BarTender出现条码打印位置不准的情况怎么办
在使用BarTender 2016设计打印条码标签,往往在打印时会遇到各种各样的问题,比如说:打印内容错位,内容发生偏移,与设置好的BarTender 2016条码标签的相对位置发生较为严重的偏差,这 ...
- Hibernate_day04讲义_使用Hibernate完成对客户的条件查询