【Spring源代码阅读之七】执行postProcessBeanFactory方法对@Configuration配置类的@Bean方法进行CGLIB代理增强

允我心安 提交于 2020-03-01 01:49:52

导图

在这里插入图片描述

在哪调用到这里的

在这里插入图片描述

ConfigurationClassPostProcessor#postProcessBeanFactory

/**
 * 使用CGLIB代理增强@Configuration配置类
 */
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	/**
	 * 根据beanFactory,生成factoryId并做去重判断,避免重复解析
	 */
	int factoryId = System.identityHashCode(beanFactory);
	if (this.factoriesPostProcessed.contains(factoryId)) {
		throw new IllegalStateException(
				"postProcessBeanFactory already called on this post-processor against " + beanFactory);
	}
	this.factoriesPostProcessed.add(factoryId);
	/**
	 * 如果生成的ID并没有在registriesPostProcessed集合中,证明BeanFactory不受BeanDefinitionRegistryPostProcessor
	 * 接口的支持,所以需要解析BeanFactory中的配置类
	 */
	if (!this.registriesPostProcessed.contains(factoryId)) {
		// BeanDefinitionRegistryPostProcessor hook apparently not supported...
		// Simply call processConfigurationClasses lazily at this point then.
		processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
	}

	/**
	 * 对配置类加上CGLIB代理
	 */
	enhanceConfigurationClasses(beanFactory);
	/**
	 * 注册ImportAware后置处理器
	 */
	beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

enhanceConfigurationClasses

/**
 * 解析配置类,如果需要对Bean进行代理则进行代理
 */
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
	/**
	 * 定义一个集合,存放需要被代理的Bean
	 */
	Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
	/**
	 * 获取容器中的BeanName,进行遍历
	 */
	for (String beanName : beanFactory.getBeanDefinitionNames()) {
		/**
		 * 根据BeanName获得对应的BeanDefinition
		 */
		BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
		/**
		 * 判断BeanDefinition是否是一个全配置类
		 * 		存在@Configuration注解就是全配置类
		 * 		存在@ComponentScan、@Import等等就不是全配置类(半配置类)	
		 */
		if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
			/**
			 * 如果BeanDefinition不是AbstractBeanDefinition的子类,则不能给其进行代理
			 */
			if (!(beanDef instanceof AbstractBeanDefinition)) {
				throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
						beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
			}
			else if (logger.isWarnEnabled() && beanFactory.containsSingleton(beanName)) {
				logger.warn("Cannot enhance @Configuration bean definition '" + beanName +
						"' since its singleton instance has been created too early. The typical cause " +
						"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
						"return type: Consider declaring such methods as 'static'.");
			}
			/**
			 * 放入集合中准备代理
			 */
			configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
		}
	}
	/**
	 * 如果集合为空则没有需要代理的类
	 */
	if (configBeanDefs.isEmpty()) {
		// nothing to enhance -> return immediately
		return;
	}

	/**
	 * 创建进行CGLIB代理的对象
	 */
	ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
	/**
	 * 遍历需要代理的对象
	 */
	for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
		/**
		 * 获取BeanDefinition
		 */
		AbstractBeanDefinition beanDef = entry.getValue();
		// If a @Configuration class gets proxied, always proxy the target class
		/**
		 * 给BeanDefinition设置标识,证明此BeanDefinition会永久被代理
		 */
		beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
		try {
			// Set enhanced subclass of the user-specified bean class
			/**
			 * 获得需要代理的BeanDefinition代表的类的Class
			 */
			Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
			/**
			 * 目标Class真实存在的话就为其生成代理Class
			 */
			if (configClass != null) {
				/**
				 * 生成代理Class
				 */
				Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
				/**
				 * 如果目标Class和代理Class不一样的话,就证明生成成功,进行替换
				 */
				if (configClass != enhancedClass) {
					if (logger.isDebugEnabled()) {
						logger.debug(String.format("Replacing bean definition '%s' existing class '%s' with " +
								"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
					}
					/**
					 * 将BeanDefinition中的BeanClass替换成代理Class,完成代理
					 */
					beanDef.setBeanClass(enhancedClass);
				}
			}
		}
		catch (Throwable ex) {
			throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
		}
	}
}

ConfigurationClassEnhancer#enhance

/**
 * 判断类是否被代理过,没有被代理过时再为其生成代理
 */
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
	/**
	 * 判断类是否实现了EnhancedConfiguration接口,实现了的话就证明类已经被代理了
	 * 因为代理类都实现了该接口,就将已经被代理的类返回去
	 */
	if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
		if (logger.isDebugEnabled()) {
			logger.debug(String.format("Ignoring request to enhance %s as it has " +
					"already been enhanced. This usually indicates that more than one " +
					"ConfigurationClassPostProcessor has been registered (e.g. via " +
					"<context:annotation-config>). This is harmless, but you may " +
					"want check your configuration and remove one CCPP if possible",
					configClass.getName()));
		}
		return configClass;
	}
	/**
	 * 到这里的话就证明没有被代理过,就进行代理的逻辑,并返回代理的对象
	 */
	Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
	if (logger.isDebugEnabled()) {
		logger.debug(String.format("Successfully enhanced %s; enhanced class name is: %s",
				configClass.getName(), enhancedClass.getName()));
	}
	return enhancedClass;
}

newEnhancer

/**
 * 创建CGLIB代理,这里面都是CGLIB代理的知识
 */
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
	/**
	 * 创建一个代理对象
	 */
	Enhancer enhancer = new Enhancer();
	/**
	 * 给定代理对象的父类,父类就是我们程序员编写的@Configuration配置类
	 */
	enhancer.setSuperclass(configSuperClass);
	/**
	 * 给代理对象实现一个接口,这个接口实现了BeanFactoryAware接口,可获取BeanFactory工厂
	 */
	enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
	/**
	 * 生成的代理类不实现Factory接口
	 */
	enhancer.setUseFactory(false);
	/**
	 * 命名策略,对生成的代理类的类名标记做重新定义
	 */
	enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
	/**
	 * 生成proxy的策略,采用我们的classloader替换线程上下文的classloader去加载proxy
	 */
	enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
	/**
	 * 设置方法回调,当调用代理类的方法时会回调这些
	 */
	enhancer.setCallbackFilter(CALLBACK_FILTER);
	/**
	 * 设置回调的类型
	 */
	enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
	/**
	 * 返回代理类
	 */
	return enhancer;
}

CALLBACK_FILTER


private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);
/**
 * 生成代理的回调
 */
private static final Callback[] CALLBACKS = new Callback[] {
		/**
		 *  检测类是否有方法包含@Bean,生成bean
		 */
		new BeanMethodInterceptor(),
		/**
		 * 实现了BeanFactoryAware的方法,通过反射调用setBeanFactory方法传入beanFactory
		 */
		new BeanFactoryAwareMethodInterceptor(),
		NoOp.INSTANCE
};

ConfigurationClassEnhancer.BeanMethodInterceptor

类的注释理解

	/**
	 * 拦截对任何{@link Bean}注释方法的调用,以确保正确处理Bean语义,如作用域和AOP代理。
	 */
	private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
BeanMethodInterceptor#intercept
/**
 * 增强@Bean注释存在的方法
 * @param enhancedConfigInstance 代理对象
 * @param beanMethod 原始类的方法引用
 * @param beanMethodArgs 方法参数列表
 * @param cglibMethodProxy 代理对象的代理方法的引用
 */
@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
			MethodProxy cglibMethodProxy) throws Throwable {

	/**
	 * 获得BeanFactory
	 */
	ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
	/**
	 * 获得原始方法返回对象使用的BeanName
	 */
	String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);

	// Determine whether this bean is a scoped-proxy
	/**
	 * 获得原始方法上的@Scope注解,如果指定了动态代理模型,则为其生成动态代理模型特征的BeanName
	 */
	Scope scope = AnnotatedElementUtils.findMergedAnnotation(beanMethod, Scope.class);
	if (scope != null && scope.proxyMode() != ScopedProxyMode.NO) {
		String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
		if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
			beanName = scopedBeanName;
		}
	}

	// To handle the case of an inter-bean method reference, we must explicitly check the
	// container for already cached instances.

	// First, check to see if the requested bean is a FactoryBean. If so, create a subclass
	// proxy that intercepts calls to getObject() and returns any cached bean instance.
	// This ensures that the semantics of calling a FactoryBean from within @Bean methods
	// is the same as that of referring to a FactoryBean within XML. See SPR-6602.
	/**
	 * 这里是对FactoryBean的处理,如果BeanFactory中存在BeanName的定义
	 * 并且存在'&'+BeanName的定义(BeanFactory默认BeanName)存在
	 * 则认为方法返回的类型是BeanFactory类型,则还需要对getObject()方法进行代理
	 * 也就是说代理中又有代理
	 */
	if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
			factoryContainsBean(beanFactory, beanName)) {
		Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
		/**
		 * 如果原始方法返回类型是FactoryBean同时又继承了ScopedProxyFactoryBean接口,则不需要进一步代理
		 */
		if (factoryBean instanceof ScopedProxyFactoryBean) {
			// Scoped proxy factory beans are a special case and should not be further proxied
		}
		else {
			// It is a candidate FactoryBean - go ahead with enhancement
			/**
			 * 对FactoryBean进一步代理(暂时不研究)
			 */
			return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
		}
	}

	/**
	 * 判断是执行方法创建对象返回还是从容器中拿对象返回
	 */
	if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
		// The factory is calling the bean method in order to instantiate and register the bean
		// (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
		// create the bean instance.
		if (logger.isWarnEnabled() &&
				BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
			logger.warn(String.format("@Bean method %s.%s is non-static and returns an object " +
							"assignable to Spring's BeanFactoryPostProcessor interface. This will " +
							"result in a failure to process annotations such as @Autowired, " +
							"@Resource and @PostConstruct within the method's declaring " +
							"@Configuration class. Add the 'static' modifier to this method to avoid " +
							"these container lifecycle issues; see @Bean javadoc for complete details.",
					beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
		}
		/**
		 * 执行原始方法创建对象返回
		 */
		return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
	}

	/**
	 * 从容器中获取对象返回
	 */
	return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}
BeanAnnotationHelper#determineBeanNameFor
/**
 * 获得@Bean方法返回对象的BeanName,默认使用方法名,如果在@Bean注解中指定,则使用注解中的
 * 若指定多个,则使用第一个
 */
public static String determineBeanNameFor(Method beanMethod) {
	// By default, the bean name is the name of the @Bean-annotated method
	String beanName = beanMethod.getName();
	// Check to see if the user has explicitly set a custom bean name...
	Bean bean = AnnotatedElementUtils.findMergedAnnotation(beanMethod, Bean.class);
	if (bean != null) {
		String[] names = bean.name();
		if (names.length > 0) {
			beanName = names[0];
		}
	}
	return beanName;
}
isCurrentlyInvokedFactoryMethod
/**
 * 这是一个思想很牛逼的判断
 * 首先获得调用此方法的工厂方法,也就是Spring容器中调用@Bean方法的方法
 * 判断是创建还是获取,分为四种情况:
 * 		1、如果工厂方法不存在,就是为null,证明是外部调用的此方法,这时Spring容器中的Bean已经实例化完毕
 * 			,这时就会返回false,证明不需要执行方法创建,直接从容器中拿对象
 * 		2、工厂方法存在,则证明是Spring容器内部方法调用的此方法,判断方法名,一致则是代理方法调用原始方法
 * 			,这时返回true,则执行方法创建对象
 * 		3、工厂方法存在,方法名不一样,这时返回false,则从容器中拿对象
 * 		4、比较参数类型只是为了解决协变返回类型的潜在问题(只发生在Groovy类上,不研究)
 *
 * 解释:对2、3情况的解释:
 * @Bean
 * public A a(){
 *     return new A();
 * }
 * @Bean
 * public B b(){
 *     a();
 *     return new B();
 * }
 *
 * 第二种情况:当执行代理对象的a()方法时,CGLIB会执行拦截,原因是为了保证单例原则,这时执行MethodInterceptor
 * 的intercept方法,会有一个原始方法的引用参数,这时,就是本方法的这一个参数,这时原始方法是被调用者,代理方法
 * 是调用者,这时调用者是代理对象的a()方法,被调用者是原始对象的a()方法,方法名一致,执行原始方法创建对象
 * 第三种情况:当执行代理对象的b()方法时,CGLIB会执行拦截,如同第二种情况,会执行原始方法创建对象,但是执行到
 * 原始方法中的第一行代码时,调用a()方法时,CGLIB又会执行一次拦截,这时原始方法是a()方法,而调用方法是原始方法b(),
 * 这时他们方法名不一样,则b()方法中调用a()方法,a()方法不会创建对象,而是从容器中拿a()方法对应的对象
 *
 * 这里可以简单写一个例子打上断点有助于理解
 */
private boolean isCurrentlyInvokedFactoryMethod(Method method) {
	Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
	return (currentlyInvoked != null && method.getName().equals(currentlyInvoked.getName()) &&
			Arrays.equals(method.getParameterTypes(), currentlyInvoked.getParameterTypes()));
}
resolveBeanReference
/**
 * 从容器中获取对象
 * @param beanMethod 原始方法引用
 * @param beanMethodArgs 方法参数
 * @param beanFactory BeanFactory工厂
 * @param beanName BeanName
 */
private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
		ConfigurableBeanFactory beanFactory, String beanName) {

	// The user (i.e. not the factory) is requesting this bean through a call to
	// the bean method, direct or indirect. The bean may have already been marked
	// as 'in creation' in certain autowiring scenarios; if so, temporarily set
	// the in-creation status to false in order to avoid an exception.
	/**
	 * 获得beanName对应的对象的创建状态,
	 */
	boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
	try {
		/**
		 * 如果状态是正在创建中,则临时设置为不在创建中,最后在finally代码块中再设置回来
		 */
		if (alreadyInCreation) {
			beanFactory.setCurrentlyInCreation(beanName, false);
		}
		/**
		 * 判断参数列表是否异常
		 */
		boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
		/**
		 * 参数数组有效并且是单例对象,则进行参数有效性判断,即参数中不能有null的存在
		 * 如果存在空参数,则只是为了引用的目的,所以他们不能是可选的,所以置为false
		 */
		if (useArgs && beanFactory.isSingleton(beanName)) {
			// Stubbed null arguments just for reference purposes,
			// expecting them to be autowired for regular singleton references?
			// A safe assumption since @Bean singleton arguments cannot be optional...
			for (Object arg : beanMethodArgs) {
				if (arg == null) {
					useArgs = false;
					break;
				}
			}
		}
		/**
		 * 通过以上判断
		 * 	1、参数数组中都是有效的参数,没有null参数的存在,可以在获取并创建对象时使用指定参数创建
		 * 	2、参数数组为空或者参数数组中有null的存在,则不使用参数获取或创建对象
		 */
		Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
				beanFactory.getBean(beanName));
		/**
		 * 判断容器中的对象能否赋值给@Bean方法的返回类型,其实就是判断对象是否与@Bean方法的返回类型一致
		 */
		if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
			// Detect package-protected NullBean instance through equals(null) check
			/**
			 * 在不一致的情况下,判断实例是否为null
			 */
			if (beanInstance.equals(null)) {
				if (logger.isDebugEnabled()) {
					logger.debug(String.format("@Bean method %s.%s called as bean reference " +
							"for type [%s] returned null bean; resolving to null value.",
							beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
							beanMethod.getReturnType().getName()));
				}
				beanInstance = null;
			}
			else {
				String msg = String.format("@Bean method %s.%s called as bean reference " +
						"for type [%s] but overridden by non-compatible bean instance of type [%s].",
						beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
						beanMethod.getReturnType().getName(), beanInstance.getClass().getName());
				try {
					BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
					msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription();
				}
				catch (NoSuchBeanDefinitionException ex) {
					// Ignore - simply no detailed message then.
				}
				throw new IllegalStateException(msg);
			}
		}
		/**
		 * 获取方法调用者,存在的话就将被调用者设置依赖Bean,
		 * 调用者依赖了被调用者,被调用者销毁的话则先销毁调用者
		 */
		Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
		if (currentlyInvoked != null) {
			String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
			beanFactory.registerDependentBean(beanName, outerBeanName);
		}
		return beanInstance;
	}
	finally {
		if (alreadyInCreation) {
			beanFactory.setCurrentlyInCreation(beanName, true);
		}
	}
}

ConfigurationClassEnhancer.BeanFactoryAwareMethodInterceptor

/**
 * Intercepts the invocation of any {@link BeanFactoryAware#setBeanFactory(BeanFactory)} on
 * {@code @Configuration} class instances for the purpose of recording the {@link BeanFactory}.
 * @see EnhancedConfiguration
 */
private static class BeanFactoryAwareMethodInterceptor implements MethodInterceptor, ConditionalCallback {

	@Override
	@Nullable
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		/**
		 * 获得代理对象中BeanFactory类型的全局变量,变量名称已固定
		 */
		Field field = ReflectionUtils.findField(obj.getClass(), BEAN_FACTORY_FIELD);
		Assert.state(field != null, "Unable to find generated BeanFactory field");
		/**
		 * 存在的话就将Spring中默认的BeanFactory设置给这个属性
		 */
		field.set(obj, args[0]);

		// Does the actual (non-CGLIB) superclass implement BeanFactoryAware?
		// If so, call its setBeanFactory() method. If not, just exit.
		/**
		 * 实际原始类是否实现了BeanFactoryAware接口,实现则调用,否则直接返回
		 */
		if (BeanFactoryAware.class.isAssignableFrom(ClassUtils.getUserClass(obj.getClass().getSuperclass()))) {
			return proxy.invokeSuper(obj, args);
		}
		return null;
	}

	@Override
	public boolean isMatch(Method candidateMethod) {
		return isSetBeanFactory(candidateMethod);
	}

	public static boolean isSetBeanFactory(Method candidateMethod) {
		return (candidateMethod.getName().equals("setBeanFactory") &&
				candidateMethod.getParameterCount() == 1 &&
				BeanFactory.class == candidateMethod.getParameterTypes()[0] &&
				BeanFactoryAware.class.isAssignableFrom(candidateMethod.getDeclaringClass()));
	}
}

createClass

/**
 * 根据动态代理对象生成Class文件
 */
private Class<?> createClass(Enhancer enhancer) {
	Class<?> subclass = enhancer.createClass();
	// Registering callbacks statically (as opposed to thread-local)
	// is critical for usage in an OSGi environment (SPR-5932)...
	/**
	 * 没有使用过,暂时不理解
	 * 静态注册回调(而不是线程本地)对于在OSGi环境(SPR-5932)中使用至关重要
	 */
	Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
	return subclass;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!