执行ConfigurationClassPostProcessor#postProcessBeanFactory方法对@Configuration配置类的@Bean方法进行CGLIB代理增强
导图
在哪调用到这里的
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;
}
来源:CSDN
作者:洋洋代码
链接:https://blog.csdn.net/weixin_42997554/article/details/104578710