前言
上篇博客基本梳理了一下@Configuration注解的类注册源码上的一些细节和流程。
一个实例
准备三个类,一个配置类,两个普通类,其中一个普通类可以什么都不做
@Component
public class TestBean {
//这个普通类里面只有一个构造方法
public TestBean() {
System.out.println("this is testBean one constructor method");
}
}
/**
* autor:liman
* createtime:2020/4/6
* comment:
*/
public class TestBean02 {
}
配置类
@Configuration
@ComponentScan(value="com.learn.importselector.config")
public class AppConfig {
@Bean
public TestBean testBean(){
return new TestBean();
}
@Bean
public TestBean02 testBean02(){
testBean();//这里也会调用testBean方法。
return new TestBean02();
}
}
问题:TestBean的构造方法会被调用几次?注意在TestBean02中也会调用testBean方法。
引入一个测试代码
public class TestOutOfConfig {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext
= new AnnotationConfigApplicationContext(AppConfig.class);
TestBean02 testBean = annotationConfigApplicationContext.getBean(TestBean02.class);
}
}
答案:如果加上了@Configuration,则只会调用一次,如果去掉@Configuration注解则会调用两次
运行情况:
加入了@Configuration注解后的运行情况
取消@Configuration注解后的运行情况
问题:@Configuration到底干了啥?为啥去掉@Configuration之后会调用两次?
CGLIB代理的简单实例
其实之前总结过代理,这里还是想说一下CGLIB的代理,因为后面的源码阅读会用到
一个目标类
/**
* autor:liman
* createtime:2020/4/11
* comment:
*/
public class HelloService {
public HelloService(){
System.out.println("this is construct method of HelloService");
}
//这个方法不会被代理,因为是final方法
final public String sayOthers(String name){
System.out.println("hello service to others : "+name);
return null;
}
public void sayHello(){
System.out.println("helloService:sayHello");
}
}
一个方法调用拦截器
public class SelfMethodInterceptor implements MethodInterceptor {
/**
*
* @param o 目标对象
* @param method 目标方法
* @param objects 目标方法参数
* @param methodProxy 目标方法的代理类 methodProxy.invokeSuper()
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("self interceptor before");
System.out.println(method.getName());//sayHello()
methodProxy.invokeSuper(o,objects);
System.out.println(methodProxy.getClass().getSimpleName());
System.out.println(methodProxy.getSignature());//代理后的方法
System.out.println("self interceptor after");
return null;
}
}
调用的实例
/**
* autor:liman
* createtime:2020/4/11
* comment:这里需要引入CGLIB的调用包
*/
public class CglibTest {
public static void main(String[] args) {
//将生成的代理类导入到指定文件夹,可以查看CGLIB生成的代理类的class源码
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"E:\\cglib_class");
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(HelloService.class);
enhancer.setCallback(new SelfMethodInterceptor());
HelloService proxy = (HelloService) enhancer.create();
proxy.sayHello();
}
}
依旧是个前提
我们这篇博客是要总结@Configuration这个注解spring底层到底干了什么,这里我们就从上篇博客的后续开始,还是贴入我们讨论了很多次的方法
//TODO :PostProcessorRegistrationDelegate中的第56行
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
//TODO: 定义一个容器,表示已经处理过了的BeanFactoryPostProcessor
Set<String> processedBeans = new HashSet<>();
//TODO:如果BeanFactory是一个注册器(这个好像必会进入)
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//TODO:这里定义了两个集合,一个是BeanFactoryPostProcessor,一个是BeanDefinitionRegistryPostProcessor
//TODO:放自定义的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//TODO:BeanDefinitionRegistryPostProcessor只是继承了BeanFactoryPostProcessor接口而已
//TODO:放自定义的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
//TODO : 遍历传入过来的集合beanFactoryPostProcessors
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
//TODO:如果自定义的BeanFactoryPostProcessor实现了BeanDefinitionRegistryPostProcessor接口
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {//TODO:如果是BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);//TODO:调用postProcessor其中的方法
registryProcessors.add(registryProcessor);
}
else {//TODO:如果自定义的BeanFactoryPostProcessor没有实现现BeanDefinitionRegistryPostProcessor接口
regularPostProcessors.add(postProcessor); //TODO:将自定义的BeanFactoryProcessor放到上面定义的集合中
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
//TODO:又定义一个集合存放BeanDefinitionRegistryPostProcessor,这个集合存放的是spring内部实现了这个接口的类
//TODO:放spring内部定义的BeanDefinitionRegistryPostProcessor
//TODO:每次真正调用的,才是这个集合中的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
//TODO:根据bean的类型获取bean的名称,这里获取的是BeanDefinitionRegistryPostProcessor类型的
//TODO:首先调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
//TODO:根据Type获取对应类型的beanName,这里才会获取出内部定义的ConfigurationClassPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
//TODO:遍历上面获得的postProcessorNames,并根据每个beanName获取对应的beanDefinition,然后放到currentRegistryProcessors中
//TODO:如果没有自定义的,则这个时候这里就一个
//TODO:同时将遍历的每一个beanName放到processedBeans中
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
//TODO:将 ConfigurationClassPostProcessor 标记为已经处理
processedBeans.add(ppName);
}
}
//TODO:设置排序,不重要
sortPostProcessors(currentRegistryProcessors, beanFactory);
//TODO:合并两个集合,将spring自定义的Processors加入到registryProcessors中,可以看到所谓的currentRegistryProcessors就是一个过渡的
registryProcessors.addAll(currentRegistryProcessors);
//TODO:真正的开始调用BeanDefinitionRegistryPostProcessor中的方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//TODO:清空currentRegistryProcessors,这里就清除了 ConfigurationClassPostProcessor
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
//TODO:开始调用实现了Ordered接口的BeanDefinitionRegistryPostProcessor类
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
//TODO:和上面的操作一样,但是这个时候 currentRegistryProcessors 中只会有实现了Ordered接口的BeanDefinitionRegistryPostProcessor
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
//TODO:最后,调用其他的BeanDefinitionRegistryPostProcessors,直到没有更多的BeanDefinitionRegistryPostProcessors实现类
//TODO:简单点说这里就是在扫除剩余的没被调用的BeanDefinitionRegistryPostProcessors实例
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
//TODO:到这里,调用postProcessBeanFactory(即BeanDefinitionRegistryPostProcessors的父类)的回调方法,这里面就有针对@Configuration类的增强操作
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
//TODO:如果一个beanFactory不是注册器,这个应该是一个兼容操作,老版本的spring的BeanFactory是没有实现Registry接口的
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
//TODO:开始处理 BeanFactoryProcessor 类型的类,并回调指定的方法(就是只实现了BeanFactoryPorcessor接口的类)
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
//TODO:如果已经在processedBeans集合中,这里不再做处理
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();//TODO:存放实现了 PriorityOrdered 接口的 BeanFactoryProcessor
List<String> orderedPostProcessorNames = new ArrayList<>(); //TODO:存放实现了 Ordered 接口的 BeanFactoryProcessor
List<String> nonOrderedPostProcessorNames = new ArrayList<>();//TODO:存放没有实现 Ordered 接口也没有实现 PriorityOrdered 的 BeanFactoryProcessor
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
//TODO:调用实现了PriorityOrdered接口的BeanFactoryPostProcessor回调方法
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
//TODO:调用实现了Ordered接口的 BeanFactoryPostProcessors 回调方法
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
//TODO:最后,处理两个接口为没有实现的正常的 BeanFactoryPostProcessors 回调方法
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
这里再次总结一下spring中回调BeanFactoryPostProcessor接口实现类的方法,就是上面这段代码,invokeBeanFactoryPostProcessors方法。
这个方法在AbstractApplicationContext类中被调用的时候,传入进来的是这样的
//TODO:通过委托对象调用指定的BeanFactoryPostProcessor(这里是调用自定义的BeanFactoryPostProcessor)
//TODO:这里的getBeanFactoryPostProcessors()并不是取出spring内部定义的BeanFactoryPostProcessor,而是取出程序员自己定义的BeanFactoryPostProcessor
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
这里只需记住一点,通过getBeanFactoryPostProcessors()
得到的是我们自己定义的BeanFactoryPostProcessor 。前面我们说过,BeanFactoryPostProcessor
其实还有一个子接口BeanDefinitionRegistryPostProcessor
源码如下所示
/**
* Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for
* the registration of further bean definitions <i>before</i> regular
* BeanFactoryPostProcessor detection kicks in. In particular,
* BeanDefinitionRegistryPostProcessor may register further bean definitions
* which in turn define BeanFactoryPostProcessor instances.
*
* @author Juergen Hoeller
* @since 3.0.1
* @see org.springframework.context.annotation.ConfigurationClassPostProcessor
*/
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
接口BeanDefinitionRegistryPostProcessor
在BeanFactoryPostProcessor
的基础上扩展了一个方法。这也就意味着BeanDefinitionRegistryPostProcessor
接口有两个方法。我们看看spring是怎么处理的(其实关于spring如何调用BeanFactoryPostProcessor
后置处理的,在上面整个方法的代码中,已经通过注解给出了)。下面一段段解构上述方法。首先说明一下,在invokeBeanFactoryPostProcessors方法中,spring为了兼容原来老版本的操作,做了一个if判断,判断如果BeanFactory是BeanDefinitionRegistry的话就进入一个if语句块,如果不是,就走else分支。这里我们从if语句块开始。
1、先处理自定义的BeanFactoryPostProcessor
//TODO:如果BeanFactory是一个注册器(这个好像必会进入)
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//TODO:这里定义了两个集合,一个是BeanFactoryPostProcessor,一个是BeanDefinitionRegistryPostProcessor
//TODO:放自定义的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//TODO:BeanDefinitionRegistryPostProcessor只是继承了BeanFactoryPostProcessor接口而已
//TODO:放自定义的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
//TODO : 遍历传入过来的集合beanFactoryPostProcessors
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
//TODO:如果自定义的BeanFactoryPostProcessor实现了BeanDefinitionRegistryPostProcessor接口
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {//TODO:如果是BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);//TODO:调用postProcessor其中的方法
registryProcessors.add(registryProcessor);
}
else {//TODO:如果自定义的BeanFactoryPostProcessor没有实现现BeanDefinitionRegistryPostProcessor接口
regularPostProcessors.add(postProcessor); //TODO:将自定义的BeanFactoryProcessor放到上面定义的集合中
}
}
//............暂时省略后面的代码
}
我们说过,通过参数传递进来的beanFactoryPostProcessors
是我们自己定义的beanFactoryPostProcessors,可以很明显的看到,如果我们定义的beanFactoryPostProcessors实现了BeanDefinitionRegistryPostProcessor接口,则会被先处理,然后放入registryProcessors集合中,如果只实现了BeanFactoryPostProcessor接口,则会放入regularPostProcessors集合中。
2、开始处理spring内部实现了BeanDefinitionRegistryPostProcessor接口的实现类。
之后我们接着往下看
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
//TODO:又定义一个集合存放BeanDefinitionRegistryPostProcessor,这个集合存放的是spring内部实现了这个接口的类
//TODO:放spring内部定义的BeanDefinitionRegistryPostProcessor
//TODO:每次真正调用的,才是这个集合中的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
//TODO:根据bean的类型获取bean的名称,这里获取的是BeanDefinitionRegistryPostProcessor类型的
//TODO:首先调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
//TODO:根据Type获取对应类型的beanName,这里才会获取出内部定义的ConfigurationClassPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
//TODO:遍历上面获得的postProcessorNames,并根据每个beanName获取对应的beanDefinition,然后放到currentRegistryProcessors中
//TODO:如果没有自定义的,则这个时候这里就一个
//TODO:同时将遍历的每一个beanName放到processedBeans中
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
//TODO:将 ConfigurationClassPostProcessor 标记为已经处理
processedBeans.add(ppName);
}
}
//TODO:设置排序,不重要
sortPostProcessors(currentRegistryProcessors, beanFactory);
//TODO:合并两个集合,将spring自定义的Processors加入到registryProcessors中,可以看到所谓的currentRegistryProcessors就是一个过渡的
registryProcessors.addAll(currentRegistryProcessors);
//TODO:真正的开始调用BeanDefinitionRegistryPostProcessor中的方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
//TODO:清空currentRegistryProcessors,这里就清除了 ConfigurationClassPostProcessor
currentRegistryProcessors.clear();
我们发现又定义了一个currentRegistryProcessors集合,这个集合其实就是用来存放待处理的BeanFactoryPostProcessor实现类。
通过如下这一句,spring获得了内部自动创建的,并且实现了BeanDefinitionRegistryPostProcessor接口的实现类。之前我们讨论过,在spring初始化过程中,会为我们自动创建六个重要的对象,这六个重要的对象中,有一个就实现了这个接口,这个就是ConfigurationClassPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
通过这一句代码,spring就获取了创建的ConfigurationClassPostProcessor对象。
我们可以看到处理的代码很简单,只是将这个对象放入currentRegistryProcessors集合中,并在invokeBeanDefinitionRegistryPostProcessors执行之后,就清空了currentRegistryProcessors集合,其中invokeBeanDefinitionRegistryPostProcessors底部就是完成ConfigurationClassPostProcessor对象中postProcessBeanDefinitionRegistry方法的回调,这个方法中就完成了包的扫描和beanDefinition的注册。
3、之后,调用实现了Ordered接口的BeanDefinitionRegistryPostProcessor和还没有被调用的BeanDefinitionRegistryPostProcessor对象。这个不太重要,但是套路都是一个
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
//TODO:开始调用实现了Ordered接口的 BeanDefinitionRegistryPostProcessor 类
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
//TODO:和上面的操作一样,但是这个时候 currentRegistryProcessors 中只会有实现了Ordered接口的BeanDefinitionRegistryPostProcessor
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
//TODO:最后,调用其他的BeanDefinitionRegistryPostProcessors,直到没有更多的BeanDefinitionRegistryPostProcessors实现类
//TODO:简单点说这里就是在扫除剩余的没被调用的BeanDefinitionRegistryPostProcessors实例
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
4、之后回调BeanFactoryPostProcessor对象中的postProcessBeanFactory方法
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
//TODO:到这里,调用postProcessBeanFactory(即BeanDefinitionRegistryPostProcessors的父类)的回调方法,这里面就有针对@Configuration类的增强操作
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
后面的代码大同小异,只是针对spring框架中内部实现了BeanFactoryPostProcessor接口的类,整个方法梳理到这里,我们至少可以得出一个结论。在这个比较复杂的方法中,spring是先处理的BeanDefinitionRegistryPostProcessor的回调,再处理的BeanFactoryPostProcessor的回调(或者你会说废话)但是接下来的东西就比较重要了,我们说过spring内部定义的一个类ConfigurationClassPostProcessor即实现了BeanDefinitionRegistryPostProcessor接口,也实现了BeanFactoryPostProcessor接口,那么根据我们刚才得出的结论,我们就可以得出,spring是先回调ConfigurationClassPostProcessor类中的postProcessBeanDefinitionRegistry方法,再回调ConfigurationClassPostProcessor类中的postProcessBeanFactory方法。
上一篇博客中,我们详细介绍了spring回调ConfigurationClassPostProcessor类中的postProcessBeanDefinitionRegistry方法的操作,spring就是在这个方法底层完成了扫描和@Import注解的处理,同时也标记出了@Configuration类,这个方法的回调工作就完成了。但是我们开头说了,针对@Configuration标记的类,可不简单的标记扫描注册就完事,至少还要有个代理。至少要避免我们开头那种操作(调用两次实例化方法的操作)
@Configuration的面纱
从 ConfigurationClassPostProcessor 回调postProcessBeanFactory方法说起。
/**
* TODO:ConfigurationClassPostProcessor第243行
* TODO:这里会完成对@Configuration的增强处理
* Prepare the Configuration classes for servicing bean requests at runtime
* by replacing them with CGLIB-enhanced subclasses.
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
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);
if (!this.registriesPostProcessed.contains(factoryId)) {
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
//如果配置类没有注册的话,完成一次注册
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
//TODO:对@Configuration实现增强处理
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
于是我们发现有个enhanceConfigurationClasses的方法,enhance就是增强的意思。说明spring底层对@Configuration标记的类进行了一个增强。继续进入
/**
* TODO:onfigurationClassPostProcessor 第338行
* TODO:对@Configuration进行增强处理
* Post-processes a BeanFactory in search of Configuration class BeanDefinitions;
* any candidates are then enhanced by a {@link ConfigurationClassEnhancer}.
* Candidate status is determined by BeanDefinition attribute metadata.
* @see ConfigurationClassEnhancer
*/
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
//TODO://是否是一个全代理的类(是否加了@Configuration)
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
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.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
logger.info("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'.");
}
//TODO:如果加了@Configuration 则放入configBeanDefs集合中
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
if (configBeanDefs.isEmpty()) {
// nothing to enhance -> return immediately
return;
}
//TODO:对@Configuration的类进行增强
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
// If a @Configuration class gets proxied, always proxy the target class
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
try {
// Set enhanced subclass of the user-specified bean class
Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
if (configClass != null) {
//TODO:进行增强
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
beanDef.setBeanClass(enhancedClass);
}
}
}
catch (Throwable ex) {
throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}
可以看到这个方法比较简单,也就是遍历了BeanDefinition的名字,然后通过名字取出指定的BeanDefinition ,判断这个BeanDefinition是否是@Configuration标记的类,如果是则放入configBeanDefs集合中。之后遍历这个集合对每一个@Configuration进行代理操作。所以核心就是下面这一行
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
继续往下
/**
* TODO:ConfigurationClassEnhancer中的第97行
* Loads the specified class and generates a CGLIB subclass of it equipped with
* container-aware callbacks capable of respecting scoping and other bean semantics.
* @return the enhanced subclass
*/
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
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;
}
//TODO:利用CGLIB创建增强类,newEnhancer完成具体的增强属性的设置
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
if (logger.isTraceEnabled()) {
logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
configClass.getName(), enhancedClass.getName()));
}
return enhancedClass;
}
通过spring本身的英文注释就能看出,这是一个通过CGLIB生成代理子类的方法(这也就是我为啥要在开头列出一个CGLIB的实例的原因),如果不熟悉CGLIB的就看文章开头的那个实例。
之后进入到createClass中的newEnhancer方法中
/**
* TODO:ConfigurationClassEnhancer第122行
* TODO:创建一个基于CGLIB的增强类
* Creates a new CGLIB {@link Enhancer} instance.
*/
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
Enhancer enhancer = new Enhancer();
//TODO:将当前配置了设置成父类
enhancer.setSuperclass(configSuperClass);
//TODO:让代理类实现EnhancedConfiguration接口,这个接口继承了BeanFactoryAware接口,可让我们的代理类获得BeanFactory便于重新注册相关bean
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
enhancer.setUseFactory(false);//TODO:代理类的产生不利用工厂模式
//TODO:命名策略
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
//TODO:设置CGLIB的生成策略
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
//TODO:设置最终代理类的回调拦截器
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
//TODO:返回生成的代理类
return enhancer;
}
文章开头的那个实例中说过,CGLIB的代理的增强逻辑主要就在拦截器中,我们看到, enhancer.setCallbackFilter(CALLBACK_FILTER);这个不就是设置代理的逻辑么,继续进入
// The callbacks to use. Note that these callbacks must be stateless.
private static final Callback[] CALLBACKS = new Callback[] {
new BeanMethodInterceptor(),
new BeanFactoryAwareMethodInterceptor(),
NoOp.INSTANCE
};
private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);
发现给@Configuration标记的类主要的代理逻辑就在BeanMethodInterceptor
和BeanFactoryAwareMethodInterceptor
中重点看这两个类中的intercept方法即可
BeanMethodInterceptor
这个主要就是针对调用@Configuration标记的类中的@Bean方法的拦截操作
/**
* TODO:针对@Bean方法的增强
* Enhance a {@link Bean @Bean} method to check the supplied BeanFactory for the
* existence of this bean object.
* @throws Throwable as a catch-all for any exception that may be thrown when invoking the
* super implementation of the proxied method i.e., the actual {@code @Bean} method
*/
@Override
@Nullable
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
MethodProxy cglibMethodProxy) throws Throwable {
//TODO:获取beanFactory容器
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
// Determine whether this bean is a scoped-proxy
if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
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.
//TODO:处理@Bean方法返回FactroyBean的情况
/**
* TODO:首先,检查@Bean方法返回的是否是一个FactoryBean,如果是,则创建一个返回的FactoryBean的代理类
* TODO:底层调用FactoryBean中的getObject方法,然后返回这个对象。
*/
if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
factoryContainsBean(beanFactory, beanName)) {
Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
if (factoryBean instanceof ScopedProxyFactoryBean) {
// Scoped proxy factory beans are a special case and should not be further proxied
}
else {
//TODO:针对BeanFactory的增强操作,并调用getObject方法
// It is a candidate FactoryBean - go ahead with enhancement
return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
}
}
//TODO:针对普通的bean的处理
//TODO:为了避免出现嵌套调用的问题 isCurrentlyInvokedFactoryMethod
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.isInfoEnabled() &&
BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
logger.info(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()));
}
//TODO:调用@Configuration类中的目标方法
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}
return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}
整体来看这个方法分为三个分支,针对web操作中,@Bean注解的方法返回的bean是否是一个域级的代理;@Bean注解的方法返回的bean是否是一个FactoryBean;以及@Bean注解的方法返回的bean是一个普通的bean,如何避免被重复调用的问题,都有处理
其中isCurrentlyInvokedFactoryMethod这个判断方法就是为了避免我们开头实例中两次执行的情况。
BeanFactoryAwareMethodInterceptor
这个是针对如果这个配置类实现了BeanFactoryAware接口的拦截操作
@Override
@Nullable
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Field field = ReflectionUtils.findField(obj.getClass(), BEAN_FACTORY_FIELD);
Assert.state(field != null, "Unable to find generated BeanFactory field");
field.set(obj, args[0]);
// Does the actual (non-CGLIB) superclass implement BeanFactoryAware?
// If so, call its setBeanFactory() method. If not, just exit.
if (BeanFactoryAware.class.isAssignableFrom(ClassUtils.getUserClass(obj.getClass().getSuperclass()))) {
return proxy.invokeSuper(obj, args);
}
return null;
}
这个方法就简单的多。只是一个简单的判断,之后直接调用
总结
整篇博客预热较久,但是针对@Configuration与@ComponentScan和@Import等注解有何区别,这里似乎可以有个结论了:@Configuration标记的类在spring中会被将对应的BeanDefinition属性configurationClass标记为FULL,而其他的则会将BeanDefinition属性configurationClass标记为lite(中文为:部分)。另一个最大的区别就是加上了@Configuration注解的类,spring底层会用CGLIB对这个类做一个代理,而其他注解则不会。这就是@Configuration最特殊的地方,也是最牛逼的地方。