【黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)】
之前我们又使用 ImportBeanDefinitionRegistrar 接口来实现了bean 的加载
比ImportSelector 接口更高端了些,【还有吗?】【还有第八种】
来个新的类
package com.dingjiaxiong.bean;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;/*** ClassName: MyPostProcessor* date: 2022/10/24 16:41** @author DingJiaxiong*/public class MyPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {//后处理bean 定义注册,参数和第七种那个注册一样BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Dog.class).getBeanDefinition();beanDefinitionRegistry.registerBeanDefinition("yellow",beanDefinition);}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {}
}
可以看到,它和第七种特别像,直接把第七种贴过来都能用了,问题就有了, 为啥叫什么后处理?
一点一点来
先来一个配置类
package com.dingjiaxiong.config;import com.dingjiaxiong.bean.MyRegistrar;
import com.dingjiaxiong.service.impl.BookServiceImpl1;
import org.springframework.context.annotation.Import;/*** ClassName: SpringConfig8* date: 2022/10/24 14:52** @author DingJiaxiong*/@Import(BookServiceImpl1.class)
public class SpringConfig8 {
}
这个图书实现类,已经是好久之前的了,笔者这里再贴一下
package com.dingjiaxiong.service.impl;import com.dingjiaxiong.service.BookService;/*** ClassName: BookServiceImpl1* date: 2022/10/24 10:35** @author DingJiaxiong*/public class BookServiceImpl1 implements BookService {@Overridepublic void check() {System.out.println("book service 1...");}
}
OK,再来个运行类
package com.dingjiaxiong.app;import com.dingjiaxiong.config.SpringConfig7;
import com.dingjiaxiong.config.SpringConfig8;
import com.dingjiaxiong.service.BookService;
import com.dingjiaxiong.service.impl.BookServiceImpl1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** ClassName: App8* date: 2022/10/24 13:42** @author DingJiaxiong*/public class App8 {public static void main(String[] args) {ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig8.class);BookService bookService = ctx.getBean("bookService", BookService.class);bookService.check();}}
修改一下实现类,把它定义成一个bean
package com.dingjiaxiong.service.impl;import com.dingjiaxiong.service.BookService;
import org.springframework.stereotype.Service;/*** ClassName: BookServiceImpl1* date: 2022/10/24 10:35** @author DingJiaxiong*/@Service("bookService")
public class BookServiceImpl1 implements BookService {@Overridepublic void check() {System.out.println("book service 1...");}
}
现在结构就很清晰了,所有都在针对实现类1
OK,直接运行
调用成功【这和第八种方法暂时没关系,就只是一个简单的bean 调用】
接下来加上我们写的类
并且修改一下这个类
package com.dingjiaxiong.bean;import com.dingjiaxiong.service.impl.BookServiceImpl2;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;/*** ClassName: MyRegistrar* date: 2022/10/24 16:24** @author DingJiaxiong*/public class MyRegistrar implements ImportBeanDefinitionRegistrar {//第一个参数就是我们之前看的元数据,而且他还有一个参数,也就是这种方式比第六种更强大@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//1. 使用元数据进行判定【这里就不判了】//初始化BeanDefinition对象BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl2.class).getBeanDefinition();registry.registerBeanDefinition("bookService",beanDefinition);}
}
也就是说,我现在本身导了个 1 ,但是又用ImportBeanDefinitionRegistrar 导了个2
直接运行看看结果
结果很明显,它既没报错, 而且调用了实现类2的方法
实现类2 BookServiceImpl2
现在的意思就是1 被覆盖了,好家伙
这样子的意义是什么?前面的1 就是默认技术【比如内嵌的Tomcat、内嵌的数据源…】
而后面就是我们自己定义了一个【那万一项目组人多】
举个栗子
package com.dingjiaxiong.bean;import com.dingjiaxiong.service.impl.BookServiceImpl2;
import com.dingjiaxiong.service.impl.BookServiceImpl3;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;/*** ClassName: MyRegistrar2* date: 2022/10/24 16:24** @author DingJiaxiong*/public class MyRegistrar2 implements ImportBeanDefinitionRegistrar {//第一个参数就是我们之前看的元数据,而且他还有一个参数,也就是这种方式比第六种更强大@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//1. 使用元数据进行判定【这里就不判了】//初始化BeanDefinition对象BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl3.class).getBeanDefinition();registry.registerBeanDefinition("bookService",beanDefinition);}
}
现在的情况就是,有两个开发者,都对同一个技术进行了实现,然后!很巧的是
它俩都摆在了这儿,现在会是谁生效,直接运行
妙了,3 生效了
挪下位置
OK,效果很明显,和加载顺序有关【现在真正的问题来了,现在是配置的顺序说了算,没有东西能够管一下它俩?万一以后更多,那不乱死?】
OK,第八种加载方式就是干这事儿的
把它也加上
package com.dingjiaxiong.bean;import com.dingjiaxiong.service.impl.BookServiceImpl4;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;/*** ClassName: MyPostProcessor* date: 2022/10/24 16:41** @author DingJiaxiong*/public class MyPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {//后处理bean 定义注册,参数和第七种那个注册一样BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl4.class).getBeanDefinition();beanDefinitionRegistry.registerBeanDefinition("bookService",beanDefinition);}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {}
}
这个加载的4 ,OK,终局之战
直接运行
MyPostProcessor说了算
这就是“后” 的意义,前面的全整完之后,我一来,前面的全部没用 了
【这种后处理的机制有什么用?】
保障性工作
这就是它最牛的地方
OK,回顾一下
导入实现了BeanDefinitionRegistryPostProcessor接口的类,通过BeanDefinition的注册器注册实名bean,
实现对容器中bean的最终裁定
其实还有加载方式,但是这些够用了