Spring
环境中,若配置类添加了
@Configuration
full
的全注解,
Spring
则会对 该配置类做
cglib
的代理。
测试程序:
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
applicationContext.refresh();
Object appConfig = applicationContext.getBean("appConfig");
}
AppConfig
类,此处加了两个注解,@Configuration
@ComponentScan
其中涉及到 CONFIGURATION_CLASS_ATTRIBUTE
: full
、lite
的概念。
@Configuration
@ComponentScan("com.popcivilar.code.spring.mockaop")
public class AppConfig {
}
配置类保留 @Configuration
配置类移除 @Configuration
配置类交由 Spring管理后,会根据 CONFIGURATION_CLASS_ATTRIBUTE的 类别决定是否对该类进行cglib代理。
在 AppConfig
类中添加两个方法:在fruit()
中调用userDao2()
,一般来说,容器在初始化时,会对加了@Bean
注解的方法进行实例化生成bean
,userDao2()
方法应该会执行2
次。
@Bean
public UserDao2 userDao2(){
return new UserDao2();
}
@Bean
public Fruit fruit(){
userDao2();
return new Apple();
}
AppConfig
未添加 @Configuration
,则该类不会被cglib
代理,执行userDao2()
方法,确实会被执行两次。@Configuration
,Appconfig
被cglib
代理,第一次执行userDao2()
被执行时,确实去new
了一个对象,但在fruit()
中再次调用userDao2()
,则不会new出对象。当一个类上面加了注解 @Configuration
时候,初始化ApplicationContext
的时候, invokeBeanDefinitionRegistryPostProcessors
方法解析此类,则从map
里面遍历 BeanDefinition
,判断当前BeanDefinition
的map
里面的属性key -configurationClass
值是full
还是lite
,刚开始扫描时候为null
,则继续解析,判断若果加了@Configuration
configurationClass
的值设置为full
;
接下来 调用 invokeBeanFactoryPostPorcessors ,此方法遍历所有的BeanFactoryPostPorcessors
(包括自定义的可以修改spring
工厂) 在遍历中会调用到enhanceConfigurationClass
,此方法中获取regist
里面的所有类,遍历判断 isfullConfigurationClass
是否为full
,若为full
,存到一个LinkedHashMap
中,为lite
则不存,若map
为null
,则返回之后直接new
对象;若map
不为null
,则去完成cglib
代理的实现。
cglib
代理的实现:调用enhance()
,判断该类是否实现EnhancedConfiguration
,完成代理则会让该类去实现此接口;若没有被代理则去实现代理 enhancer.create()
创建代码对象。
cglib
创建代理类时,具体代码如下:
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(configSuperClass); //将配置类设置成父类,cglib基于继承
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class}); //将其的接口设置为EnhancedConfiguration加强功能
enhancer.setUseFactory(false);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
// 加强点 BeanMethodInterceptor BeanFactoryAwareMethodInterceptor 内部执行 intercept(),在方法前后进行拦截
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;
}
CALLBACK_FILTER
主要为 BeanMethodInterceptor
和 BeanFactoryAwareMethodInterceptor
,都是私有静态内部类。
private static final Callback[] CALLBACKS = new Callback[] {
new BeanMethodInterceptor(),//逻辑
new BeanFactoryAwareMethodInterceptor(),//设置属性 $$beanFactory
NoOp.INSTANCE
};
BeanMethodInterceptor.intercept()
逻辑:
关键点:ConfigurationClassEnhancer.BeanMethodInterceptor.isCurrentlyInvokedFactoryMethod()