Spring读源码系列07----容器扩展功能--中

Posted 大忽悠爱忽悠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring读源码系列07----容器扩展功能--中相关的知识,希望对你有一定的参考价值。

Spring读源码系列07----容器扩展功能--中


前一篇链接:

Spring读源码系列06----容器扩展功能–上


添加ApplicationContextAwareProcessor处理器

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) 
		// Tell the internal bean factory to use the context's class loader etc.
		beanFactory.setBeanClassLoader(getClassLoader());
		if (!shouldIgnoreSpel) 
			beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		//重点关注这里
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		...
	


initializeBean方法回顾(bean初始化过程)

在AbstractAutowireCapableBeanFactory#doCreateBean方法中会调用initializeBean方法来初始化bean:

             //populateBean对bean进行属性赋值  
			populateBean(beanName, mbd, instanceWrapper);
			//对bean完成相关初始化操作
			exposedObject = initializeBean(beanName, exposedObject, mbd);

initializeBean方法:

	protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) 
		if (System.getSecurityManager() != null) 
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> 
				invokeAwareMethods(beanName, bean);
				return null;
			, getAccessControlContext());
		
		else 
		//对实现了BeanNameAware,BeanClassLoaderAware和BeanFactoryAware接口的类进行相关注入处理
			invokeAwareMethods(beanName, bean);
		
            
		Object wrappedBean = bean;
		//isSynthetic是否是应用程序自身产生的bean,如果是返回false
		//如果不是,说明是用户自定义的bean,需要被后置处理器处理
		if (mbd == null || !mbd.isSynthetic()) 
		//应用后置处理器进行前置处理
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		

		try 
		//触发相关初始化方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		
		catch (Throwable ex) 
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		
		if (mbd == null || !mbd.isSynthetic()) 
			//应用bean的后置处理
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		

		return wrappedBean;
	

invokeAwareMethods

	private void invokeAwareMethods(String beanName, Object bean) 
		if (bean instanceof Aware) 
		//注入beanName
			if (bean instanceof BeanNameAware) 
				((BeanNameAware) bean).setBeanName(beanName);
			
	    //注入加载当前bean的类加载器		
			if (bean instanceof BeanClassLoaderAware) 
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) 
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				
			
	//注入BeanFactory		
			if (bean instanceof BeanFactoryAware) 
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			
		
	

applyBeanPostProcessorsBeforeInitialization

如果我们在某个BeanPostProcessor对传入的bean进行了修改,那么可以返回修改后的bean替换原来的bean

	@Override
	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException 
 
		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) 
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) 
				return result;
			
			result = current;
		
		return result;
	

invokeInitMethods

	protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable 

		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) 
			if (logger.isTraceEnabled()) 
				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			
			if (System.getSecurityManager() != null) 
				try 
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> 
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					, getAccessControlContext());
				
				catch (PrivilegedActionException pae) 
					throw pae.getException();
				
			
			else 
			//如果当前bean实现了InitializingBean,会调用其的afterPropertiesSet方法
			//因为initializeBean方法执行是在populateBean方法之后,也就是属性注入完成之后,因此该初始化方法就被称为了afterPropertiesSet,很形象
				((InitializingBean) bean).afterPropertiesSet();
			
		
        //会尝试调用当前bean实现的init-method方法   
		if (mbd != null && bean.getClass() != NullBean.class) 
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) 
				invokeCustomInitMethod(beanName, bean, mbd);
			
		
	

applyBeanPostProcessorsAfterInitialization

如果我们在某个BeanPostProcessor对传入的bean进行了修改,那么可以返回修改后的bean替换原来的bean

	@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException 
        
		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) 
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) 
				return result;
			
			result = current;
		
		return result;
	

ApplicationContextAwareProcessor探究

上面回顾了一下initializeBean方法,让我们知道了BeanPostProcessor方法的初始化前和初始化后的处理方法会在哪里被调用

下面来分析一下ApplicationContextAwareProcessor中这两个方法都做了啥吧

class ApplicationContextAwareProcessor implements BeanPostProcessor 

	private final ConfigurableApplicationContext applicationContext;

	private final StringValueResolver embeddedValueResolver;


	/**
	 * Create a new ApplicationContextAwareProcessor for the given context.
	 */
	public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) 
		this.applicationContext = applicationContext;
		this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
	


	@Override
	@Nullable
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException 
	//没有实现上面这些规定需要被当前处理器处理注入的aware接口,就跳过不进行处理
		if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
				bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
				bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
				bean instanceof ApplicationStartupAware)) 
			return bean;
		

		AccessControlContext acc = null;

		if (System.getSecurityManager() != null) 
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		

		if (acc != null) 
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> 
				invokeAwareInterfaces(bean);
				return null;
			, acc);
		
		else 
		//对实现了aware接口的bean进行处理
			invokeAwareInterfaces(bean);
		

		return bean;
	

//相信不需要我多说了
	private void invokeAwareInterfaces(Object bean) 
		if (bean instanceof EnvironmentAware) 
			((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
		
		if (bean instanceof EmbeddedValueResolverAware) 
			((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
		
		if (bean instanceof ResourceLoaderAware) 
			((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
		
		if (bean instanceof ApplicationEventPublisherAware) 
			((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
		
		if (bean instanceof MessageSourceAware) 
			((MessageSourceAware) bean).setMessageSource(this.applicationContext);
		
		if (bean instanceof ApplicationStartupAware) 
			((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
		
		if (bean instanceof ApplicationContextAware) 
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		
	



设置忽略依赖

	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) 
		// Tell the internal bean factory to use the context's class loader etc.
		beanFactory.setBeanClassLoader(getClassLoader());
		if (!shouldIgnoreSpel) 
			beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        
        //已经分析到这里了
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class); 
		...
	

ignoreDependencyInterface方法会将指定的接口加入到AbstractAutowireCapableBeanFactory的ignoredDependencyInterfaces集合

AbstractAutowireCapableBeanFactory类中的isExcludedFromDependencyCheck方法会检查

//确定给定的 bean 属性是否从依赖项检查中排除。此实现不包括由 CGLIB 定义的属性以及其类型与忽略的依赖类型匹配或由忽略的依赖接口定义的属性。
	protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) 
		return (AutowireUtils.isExcludedFromDependencyCheck(pd) ||
				this.ignoredDependencyTypes.contains(pd.getPropertyType()) ||
				AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces));
	

AutowireUtils.isExcludedFromDependencyCheck(pd):

//确定给定的 bean 属性是否从依赖项检查中排除。此实现不包括 CGLIB 定义的属性
	public static boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) 
	//当前需要被注入的属性,在对应的类中必须有相关联的set方法
		Method wm = pd.getWriteMethod();
		//没有的话,返回false
		if (wm == null) 
			return false;
		
		//不是代理类直接返回false
		if (!wm.getDeclaringClass().getName().contains("$$")) 
			// Not a CGLIB method so it's OK.
			return false;
		
		//是代理类的话,通过判断父类,即被代理类是否存在对应的set方法来决定是否可以完成依赖注入
		// It was declared by CGLIB, but we might still want to autowire it
		// if it was actually declared by the superclass.
		Class<?> superclass = wm.getDeclaringClass().getSuperclass();
		return !ClassUtils.hasMethod(superclass, wm);
	

AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces):

//返回给定 bean 属性的 setter 方法是否在任何给定接口中定义。
	public static boolean isSetterDefinedInInterface(PropertyDescriptor pd, Set<Class<?>> interfaces) 
		Method setter = pd.getWriteMethod();
		if (setter != null) 
			Class<?> targetClass = setter.getDeclaringClass();
			for (Class<?> ifc : interfaces) 
				if (ifc.isAssignableFrom(targetClass) && ClassUtils.hasMethod(ifc, setter)) 
					return true;
				
			
		
		return false;
	

总结:上面三个判断条件,其中任意一个返回true,表示当前属性的依赖注入可以跳过,因为当前需要注入的属性就是设置了被忽略的接口,或者该属性中存在相关set方法来注入aware相关接口


AbstractAutowireCapableBeanFactory#unsatisfiedNonSimpleProperties

isExcludedFromDependencyCheck方法会在unsatisfiedNonSimpleProperties方法中被调用

该方法负责寻找出当前bean中需要进行依赖注入的属性:

//返回未满足的非简单 bean 属性数组。这些可能是对工厂中其他 bean 的不满意引用。不包括简单的属性,如原语或字符串
	protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) 
		Set<String> result = new TreeSet<>();
		PropertyValues pvs = mbd.getPropertyValues();
		PropertyDescriptor[] pds = bw.getPropertyDescriptors();
		以上是关于Spring读源码系列07----容器扩展功能--中的主要内容,如果未能解决你的问题,请参考以下文章

Spring读源码系列08----容器扩展功能--下

Spring读源码系列之AOP--07---aop自动代理创建器(拿下AOP的最后一击)

Spring读源码系列01---Spring核心类及关联性介绍

Spring源码系列 — 容器Extend Point

Spring 源码分析--容器的功能扩展

Spring源码系列 — BeanDefinition扩展点