• Spring中Bean的实例化与DI的过程


    引言

    前文我们介绍了关于如何学习Spring的源码以及解析了spring中加载配置文件注册Beandefinition的过程。今天我们继续学习DI的过程。

    创建实例和DI过程

    IOC和DI都是对spring容器特性的描述。IOC指的是将实例的生命周期交给第三方管理(spring)。而DI的侧重点在于某一个类依赖了其他的实例,将实例注入到依赖它的实例的过程。所以可以很明显的看出来DI是发生在类实例已经实例化完成之后的。

    创建实例

    BeanDefinition

    BeanDefinition是对bean属性的定义,包含了bean的状态的属性,如bean的Class对象,单例还是原型等。

    Beandefinition

    上图中是BeanDefinition定义的方法,可以看出其中包括创建Bean的工厂类名称和bean的状态单例,懒加载等。

    其中大多数方法都很容易理解,有几个属性这里需要解释下。

    dependsOn

    dependsOn是指当前Beandefinition所表示的Bean依赖了其他那些bean(不包括基本数据类型),这里依赖的bean并不需要在当前Bean中声明,所以不能通过依赖注入完成,而是需要显示的定义。

    autowireCandidate

    autowireCandidate用来表示当前bean是否可以被注入到其他实例中。

    上面的内容都可以通过xml配置或者注解来配置。

    xml

    <bean scope="singleton" autowire-candidate="true" init-method="" factory-method="" lazy-init="true" >
        </bean>
    

    注解

    public class JavaBean {
        
        public void init(){
            //init
        }
    
        public void destroy(){
            //destroy
        }
        
        @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
        @Bean(initMethod = "init", destroyMethod = "destroy")
        public JavaBean getEntity(){
            return new JavaBean();
        }
    }
    
    继承体系

    BeanDefinition继承体系

    在上图中实际实际被用来实现Beandefinition的类是RootBeanDefinitionChildBeanDefinitionGenericBeanDefinition。其中GenericBeanDefinition是在spring2.5以后才出现的,spring2.5以后都建议使用GenericBeanDefinition。但是由于以前的代码都是使用RootBeanDefinitionChildBeanDefinition,所以我们也还能看到RootBeanDefinitionChildBeanDefinition这些类。

    大体流程

    同IOC一样在阅读源码前先来看看一DI的大体流程。

    DI流程

    refresh()

    在阅读IOC相关实现的时候,除开构造函数外refresh()就是我们最初的入口,当时只是看了其中的部分代码。实际上refresh()贯穿了spring启动的整个阶段。当refresh()方法执行完成时基本就代表spring正常启动了。在DI篇我们来继续看refresh()的其他的一些代码。

    public void refresh() throws BeansException, IllegalStateException {
    		synchronized (this.startupShutdownMonitor) {
    		    //读取配置文件 注册Beandefinition
    			prepareRefresh();
    			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    			prepareBeanFactory(beanFactory);
    
    			try {
    
    				postProcessBeanFactory(beanFactory);
    				invokeBeanFactoryPostProcessors(beanFactory);
    
    				registerBeanPostProcessors(beanFactory);
    
    				initMessageSource();
    
    				initApplicationEventMulticaster();
    
    				onRefresh();
    
    				registerListeners();
    
    				finishBeanFactoryInitialization(beanFactory);
    
    				finishRefresh();
    			}catch (BeansException ex) {
    				logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);
    
    				destroyBeans();
    
    				cancelRefresh(ex);
    				throw ex;
    			}
    		}
    	}
    

    BeanFactoryPostProcessor和BeanPostProcessor

    在进行bean的实例化之前会先执行BeanFactoryPostProcessor和注册BeanPostProcessor

    BeanFactoryPostProcessorBeanPostProcessor这两个接口为Spring的Bean后置处理器接口,作用是为Bean的初始化前后提供可扩展的空间。

    BeanFactoryPostProcessor

    public interface BeanFactoryPostProcessor {
    	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
    }
    

    BeanFactoryPostProcessor可以对BeanDefinition进行处理。BeanFactoryPostProcessor在容器实际实例化任何其它的bean之前读取bean的元数据,并且可以对其进行修改修改。用于在执行实例化bean之前进行调用。

    BeanPostProcessor

    public interface BeanPostProcessor {
    
    	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
    }
    

    实现BeanPostProcessor接口可以在Bean初始化的前后做一些自定义的操作,但是不能够直接操作BeanDefinition元数据。

    BeanFactoryPostProcessorBeanPostProcessor都是spring留给我们进行扩展的类。通过实现这两个接口我们可以在bean的实例化过程中添加一些自定义的操作。而需要注意的是这两个接口虽然都提供了扩展bean实例化的功能,但两者确实完全不同的:

    • BeanFactoryPostProcessor是在所有的bean都未开始实例化前调用,其可以拿到容器中所有的Beandefinition,所以可以在bean实例化前直接修改bean定义的元数据。
    • BeanPostProcessor里的实例化前后指的是调用init(init-method)方法前后,这时实际上bean已经开始了实例化(详细的可以参考类的实例化全过程),这时取到的仅仅是某一指定类的实例。即使进行修改也只是修改当前这一实例,而无法对bean的元数据修改。

    由于postProcessor可能会在bean的实例化之前进行调用,所以在实例化前context肯定需要先拿到postProcessor,这也就可以解释上面的代码中在解析完配置文件后就开始注册BeanFactoryPostProcessorBeanPostProcessor

    listener

    //tood

    具体的关于postProcessor和Listener相关会在将整体流程理顺后再详细介绍。

    finishBeanFactoryInitialization(ConfigurableListableBeanFactory)

    finishBeanFactoryInitialization方法是对bean进行实例化的入口。

    	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
    				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
    			beanFactory.setConversionService(
    					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    		}
    
    		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    		for (String weaverAwareName : weaverAwareNames) {
    			getBean(weaverAwareName);
    		}
            
    		beanFactory.setTempClassLoader(null);
    		//缓存bean定义
    		beanFactory.freezeConfiguration();
    		beanFactory.preInstantiateSingletons();
    	}
    

    方法首先查找是否开启了注册conversionService,conversionService是用于进行两个类转换的,例如之前说过了Environment类就依赖该实例将定义的变量转换为相应的类型。

    如果要开启注册conversionService,可以在配置文件中配置。

    <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
    	<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    	//property
    	</bean>
    

    接下来的代码是从bean定义中获取LoadTimeWeaverAware类型优先进行实例化。LoadTimeWeaverAware作用是当类被加载进jvm是动态的转换类。之所以优先实例化这些类是因为在实例化其他类时可能会使用到这些类,比如jpa就极度依赖这些功能。

    preInstantiateSingletons()

    	public void preInstantiateSingletons() throws BeansException {
    		List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
    
    		for (String beanName : beanNames) {
    		    //获取bean定义
    			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    			//抽象类无法实例化
    			//非单例和懒加载在需要时才实例化
    			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    				if (isFactoryBean(beanName)) {
    				    //获取factoryBean的实例
    					final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
    					boolean isEagerInit;
    					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
    						isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
    							@Override
    							public Boolean run() {
    								return ((SmartFactoryBean<?>) factory).isEagerInit();
    							}
    						}, getAccessControlContext());
    					}else {
    						isEagerInit = (factory instanceof SmartFactoryBean &&
    								((SmartFactoryBean<?>) factory).isEagerInit());
    					}
    					if (isEagerInit) {
    						getBean(beanName);
    					}
    				}else {
    					getBean(beanName);
    				}
    			}
    		}
    
    		// 实现了SmartInitializingSingleton接口的回调方法
    		// SmartInitializingSingleton接口同InitializingBean接口类似都是用于在创建bean时进行一些后置的操作 
    		// 不同之处在于InitializingBean是在每一个实例化的过程中进行调用 而SmartInitializingSingleton是在所有的单例bean被实例化后再refresh中进行回调
    		for (String beanName : beanNames) {
    			Object singletonInstance = getSingleton(beanName);
    			if (singletonInstance instanceof SmartInitializingSingleton) {
    				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
    				if (System.getSecurityManager() != null) {
    					AccessController.doPrivileged(new PrivilegedAction<Object>() {
    						@Override
    						public Object run() {
    							smartSingleton.afterSingletonsInstantiated();
    							return null;
    						}
    					}, getAccessControlContext());
    				}else {
    					smartSingleton.afterSingletonsInstantiated();
    				}
    			}
    		}
    	}
    

    preInstantiateSingletons通过一个for循环来实例化所有注册到容器中的bean定义所代表的的bean。

    在确定好每一个beanName所代表的的bean确实需要实例化后首先检查当前beanName是否实现了接口
    FactoryBeanFactoryBean是一种产生bean的bean,相当于一个bean工厂。实现FactoryBean接口允许我们生产一个具有特点类型和参数的bean,其本质上和通过xml配置实例化的bean没有区别,好处在于对于复杂对象可以代替xml中繁杂的配置项,仅通过java代码实现。

    而由于FactoryBean本身首先是一个bean,所以我们也可以在ioc容器中获取该bean的实例。如果我们通过getBean(beanName)方法获取的实际上是FactoryBean产生的实例类型,想要获取FactoryBean的实例需要使用getBean("&" + beanName)

    getBean(String)

    getBean是一个重载方法,主要还是调用doGetBean()方法实现功能。

    	protected <T> T doGetBean(
    			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
    			throws BeansException {
            //取该beanName在容器中保存的name
            //比如上面介绍的factoryBean会加一个& 以及给bean配置的别名等
    		final String beanName = transformedBeanName(name);
    		Object bean;
            //尝试从保存bean的容器中取,如果已经存在则不用再次实例化
    		Object sharedInstance = getSingleton(beanName);
    		if (sharedInstance != null && args == null) {
    			if (logger.isDebugEnabled()) {
    				if (isSingletonCurrentlyInCreation(beanName)) {
    					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
    							"' that is not fully initialized yet - a consequence of a circular reference");
    				}else {
    					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
    				}
    			}
    			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    		}else {
                //对于非单例bean 如果该bean正在被创建而又尝试再次创建则会直接抛出异常
    			if (isPrototypeCurrentlyInCreation(beanName)) {
    				throw new BeanCurrentlyInCreationException(beanName);
    			}
    
    			BeanFactory parentBeanFactory = getParentBeanFactory();
    			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    			    //!containsBeanDefinition(beanName)表示从当前容器中没有找到匹配的BeanDefinition 尝试从父容器中查找
    				String nameToLookup = originalBeanName(name);
    				if (args != null) {
    					return (T) parentBeanFactory.getBean(nameToLookup, args);
    				}else {
    					return parentBeanFactory.getBean(nameToLookup, requiredType);
    				}
    			}
    
    			if (!typeCheckOnly) {
    			    //标记当前beanName所表示的bean正在被创建或已经被创建
    				markBeanAsCreated(beanName);
    			}
    
    			try {
    				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    				//这一步根据其实现貌似主要是检查当前BeanDefinition表示的bean是否是一个抽象类,但是前面已经检查过了 这里再次检查貌似意义不大
    				checkMergedBeanDefinition(mbd, beanName, args);
    				
    				//检查是否配置了bean的依赖 如果存在则需要先实例化被依赖的bean
    				String[] dependsOn = mbd.getDependsOn();
    				if (dependsOn != null) {
    					for (String dependsOnBean : dependsOn) {
    						if (isDependent(beanName, dependsOnBean)) {
    							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    									"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
    						}
    						registerDependentBean(dependsOnBean, beanName);
    						getBean(dependsOnBean);
    					}
    				}
    
    				if (mbd.isSingleton()) {
    					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
    						@Override
    						public Object getObject() throws BeansException {
    							try {
    								return createBean(beanName, mbd, args);
    							}
    							catch (BeansException ex) {
    								destroySingleton(beanName);
    								throw ex;
    							}
    						}
    					});
    					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    				}else if (mbd.isPrototype()) {
    					Object prototypeInstance = null;
    					try {
    						beforePrototypeCreation(beanName);
    						prototypeInstance = createBean(beanName, mbd, args);
    					}
    					finally {
    						afterPrototypeCreation(beanName);
    					}
    					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    				}else {
    					String scopeName = mbd.getScope();
    					final Scope scope = this.scopes.get(scopeName);
    					if (scope == null) {
    						throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
    					}
    					try {
    						Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
    							@Override
    							public Object getObject() throws BeansException {
    								beforePrototypeCreation(beanName);
    								try {
    									return createBean(beanName, mbd, args);
    								}
    								finally {
    									afterPrototypeCreation(beanName);
    								}
    							}
    						});
    						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    					}catch (IllegalStateException ex) {
    						throw new BeanCreationException(beanName,
    								"Scope '" + scopeName + "' is not active for the current thread; " +
    								"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
    								ex);
    					}
    				}
    			}catch (BeansException ex) {
    				cleanupAfterBeanCreationFailure(beanName);
    				throw ex;
    			}
    		}
    
    		if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
    			try {
    				return getTypeConverter().convertIfNecessary(bean, requiredType);
    			}catch (TypeMismatchException ex) {
    				if (logger.isDebugEnabled()) {
    					logger.debug("Failed to convert bean '" + name + "' to required type [" +
    							ClassUtils.getQualifiedName(requiredType) + "]", ex);
    				}
    				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    			}
    		}
    		return (T) bean;
    	}
    

    方法中的try-catch块用于创建bean实例,代码很多,不过只是根据bean的作用范围来进行创建如Singleton,prototype或者session等。创建bean的过程大同小异,区别仅在与实例保存的地方。单例bean被保存在一个map中,整个程序运行期间有效。原型bean保存在另外的容器中,每一次使用时需要重新创建。

    以单例bean创建过程为例,主要实现过程都在getSingleton(...)方法中了。getSingleton(...)的主要功能就是检查bean是否已经创建,如果没创建就进行创建然后保存到容器中。创建bean的过程由一个匿名内部类实现。

    createBean(String beanName, RootBeanDefinition mbd, Object[] args)

    	protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
    			throws BeanCreationException {
    
    		resolveBeanClass(mbd, beanName);
    		try {
    			mbd.prepareMethodOverrides();
    		}catch (BeanDefinitionValidationException ex) {
    			throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
    					beanName, "Validation of method overrides failed", ex);
    		}
    
    		try {
    		    //首先尝试执行BeanPostProcessor,如果存在后置处理器 那么首先实例化bean执行处理器
    			Object bean = resolveBeforeInstantiation(beanName, mbd);
    			if (bean != null) {
    				return bean;
    			}
    		}catch (Throwable ex) {
    			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    					"BeanPostProcessor before instantiation of bean failed", ex);
    		}
            //不存在后置处理器或者存在的执行处理器过程创建实例失败或没有创建实例的动作则执行下面的方法
    		Object beanInstance = doCreateBean(beanName, mbd, args);
    		if (logger.isDebugEnabled()) {
    			logger.debug("Finished creating instance of bean '" + beanName + "'");
    		}
    		return beanInstance;
    	}
    

    上面方法中有这样一句mbd.prepareMethodOverrides()methodOverrides实际上市BeanDefinition中的一个属性。其主要用于记录在配置文件中lookup-method和replaced-method参数设置的值。详情可以看这里:methodOverrides

    doCreateBean(...)

    	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
    
    		BeanWrapper instanceWrapper = null;
    		if (mbd.isSingleton()) {
    		    //如果已经实例化需要重新实例化则从缓存中删除 重新设置
    			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    		}
    		if (instanceWrapper == null) {
    			instanceWrapper = createBeanInstance(beanName, mbd, args);
    		}
    		//more code
    	}
    

    方法开头显示创建了一个BeanWrapper的对象,BeanWrapper相当于一个代理器,Spring委托BeanWrapper来完成bean内部属性的初始化。

    上述方法代码很多,在创建阶段只需要关注前几行。如果该bean的实例未被创建则直接创建一个。创建的方法有createBeanInstance完成。

    createBeanInstance(...)

    	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
    		Class<?> beanClass = resolveBeanClass(mbd, beanName);
            //判断当前bean类是否被定义为public 非public的类无法在其他类中实例化
    		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);
    		}
    
    		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);
    			}
    		}
    
    		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    		if (ctors != null ||
    				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
    				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
    			return autowireConstructor(beanName, mbd, ctors, args);
    		}
    		return instantiateBean(beanName, mbd);
    	}
    

    该方法先是尝试查看是否配置了工厂方法,如果存在工厂方法则由工厂方法进行创建。

    接下来的几行代码是用来提升性能的。spring在创建实例后会将创建该实例的constructor方法缓存,这样下一次需要创建该bean时直接取出构造方法创建即可不需要再重新解析一次。

    如果没有工厂方法并且构造方法也没有缓存,同时没有找到有参的构造函数,那么会通过放射调用类的默认无参构造函数。

    instantiateBean(String, RootBeanDefinition)

    该实例化方法没有太多解析的必要,基本就是通过反射的原理获取无参构造函数,通过构造函数来实例化类。

    DI

    到这里为止创建一个实例的过程就完成了,接下来就是检查该实例是否需要被注入其他的属性了。

    回到doCreateBean(...)

    前面在创建bean实例时调用到了doCreateBean(...)方法,在创建好实例后的后续功能也依赖于该方法。

    	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
            // other-code
    		Object exposedObject = bean;
    		try {
    			populateBean(beanName, mbd, instanceWrapper);
    			if (exposedObject != null) {
    				exposedObject = initializeBean(beanName, exposedObject, mbd);
    			}
    		} catch (Throwable ex) {
    			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
    				throw (BeanCreationException) ex;
    			}else {
    				throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
    			}
    		}
    		// other-code
    		return exposedObject;
    	}
    

    在DI阶段我们需要关注的就上上面的代码,首先是通过populateBean方法对在配置文件中配置的property属性进行设置值。

    populateBean顾名思义就是对bean中的属性添加数据。populateBean中其实是通过后置处理器来进行属性的设置,主要的代码如下:

    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;
    			}
    		}
    	}
    }
    

    spring中默认注册了以下几种beanPostProcessor,如下:

    beanPostProcessor

    每一个beanPostProcessor都会在实例化前后相应的地方进行调用。在这里我们需要关注的是AutowiredAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor这几个注解。

    顾名思义这几个beanPostProcessor都是用来处理注解的,对应用来处理@Autowired,@Required,@Common几个注解。

    这里以@Autowored的处理为例。

    AutowiredAnnotationBeanPostProcessor

    	public PropertyValues postProcessPropertyValues(
    			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
    
    		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass());
    		try {
    			metadata.inject(bean, beanName, pvs);
    		}catch (Throwable ex) {
    			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    		}
    		return pvs;
    	}
    	
    	private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
    		LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
    		Class<?> targetClass = clazz;
    
    		do {
    			LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<InjectionMetadata.InjectedElement>();
    			for (Field field : targetClass.getDeclaredFields()) {
    				AnnotationAttributes annotation = findAutowiredAnnotation(field);
    				if (annotation != null) {
    					if (Modifier.isStatic(field.getModifiers())) {
    						if (logger.isWarnEnabled()) {
    							logger.warn("Autowired annotation is not supported on static fields: " + field);
    						}
    						continue;
    					}
    					boolean required = determineRequiredStatus(annotation);
    					currElements.add(new AutowiredFieldElement(field, required));
    				}
    			}
    			for (Method method : targetClass.getDeclaredMethods()) {
    				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
    				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
    					continue;
    				}
    				AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
    				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
    					if (Modifier.isStatic(method.getModifiers())) {
    						if (logger.isWarnEnabled()) {
    							logger.warn("Autowired annotation is not supported on static methods: " + method);
    						}
    						continue;
    					}
    					if (method.getParameterTypes().length == 0) {
    						if (logger.isWarnEnabled()) {
    							logger.warn("Autowired annotation should be used on methods with actual parameters: " + method);
    						}
    					}
    					boolean required = determineRequiredStatus(ann);
    					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
    					currElements.add(new AutowiredMethodElement(method, required, pd));
    				}
    			}
    			elements.addAll(0, currElements);
    			targetClass = targetClass.getSuperclass();
    		}
    		while (targetClass != null && targetClass != Object.class);
    
    		return new InjectionMetadata(clazz, elements);
    	}
    

    该方法主要就是通过解析当前bean有哪些属性被@Autowired注解修饰,将其封装为一个InjectionMetadata对象。解析的过程通过findAutowiringMetadata(String beanName, Class<?> clazz)完成,但实际上主要还是通过上面的buildAutowiringMetadata(Class<?> clazz)完成。

    方法比较简单,首先就是遍历bean的所有字段(Field),通过反射的方法查找字段上的注解,如果存在匹配的注解(AutowiredAnnotationBeanPostProcessor匹配的就是@Autowired)。如果存在该注解就将这个字段记录表示需要进行注入。

    当将字段遍历完成后就取出所有的方法,查找方法上是否有该注解,如果存在的话同理记录下该方法。

    对于被记录下的字段或者方法会被封装成一个InjectedElement对象。通过该对象的inject方法完成注入工作。

    protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
    		Field field = (Field) this.member;
    		try {
    			Object value;
    			if (this.cached) {
    				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    			} else {
    				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
    				desc.setContainingClass(bean.getClass());
    				Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
    				TypeConverter typeConverter = beanFactory.getTypeConverter();
    				value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    				synchronized (this) {
    					if (!this.cached) {
    						if (value != null || this.required) {
    							this.cachedFieldValue = desc;
    							registerDependentBeans(beanName, autowiredBeanNames);
    							if (autowiredBeanNames.size() == 1) {
    								String autowiredBeanName = autowiredBeanNames.iterator().next();
    								if (beanFactory.containsBean(autowiredBeanName)) {
    									if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
    										this.cachedFieldValue = new RuntimeBeanReference(autowiredBeanName);
    									}
    								}
    							}
    						} else {
    							this.cachedFieldValue = null;
    						}
    						this.cached = true;
    					}
    				}
    			}
    			if (value != null) {
    				ReflectionUtils.makeAccessible(field);
    				field.set(bean, value);
    			}
    		} catch (Throwable ex) {
    			throw new BeanCreationException("Could not autowire field: " + field, ex);
    		}
    	}
    }
    

    刚方法总体来说比较简单,首先是查询当前bean的依赖是否已经被缓存,如果缓存了则从缓存中取即可。

    如果是第一次解析则从beanfactory中获取相应的依赖属性。

    synchronized代码块主要就是将解析后的依赖的值缓存起来,建立当前bean和其依赖的属性之间的关系。当下一次创建该类型的bean时可以直接使用不需重新解析。

    而真正的属性注入是依赖着几行代码:

    if (value != null) {
    	ReflectionUtils.makeAccessible(field);
    	field.set(bean, value);
    }
    

    上面的代码没有任何的难度,就是对JDK中反射的api的使用。

    基本上后面就是重复这个过程对bean的属性进行注入,在这一过程中最重要的就是beanPostProcessor,注入都已依赖这一组完成的。

  • 相关阅读:
    Jquery、Ajax实现新闻列表页分页功能
    html中文字溢出处理(text-overflow)
    canvas图像绘制过程中的注意
    问题账户需求分析
    2016年秋季个人阅读计划
    阅读笔记之我们应当怎样做需求分析
    软件工程课个人总结
    人月神话阅读笔记—第四章
    人月神话阅读笔记—第三章
    人月神话阅读笔记—序言及第一、二章
  • 原文地址:https://www.cnblogs.com/liyus/p/11067895.html
Copyright © 2020-2023  润新知