SpringBoot
【黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)】
SpringBoot 原理篇
文章目录
- SpringBoot
- SpringBoot 原理篇
- 1 自动配置
- 1.10 bean 的加载方式【八】
- 1.10.1 BeanDefinitionRegistryPostProcessor
- 1.10.2 小结
1 自动配置
1.10 bean 的加载方式【八】
1.10.1 BeanDefinitionRegistryPostProcessor
之前我们又使用 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 {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
//后处理bean 定义注册,参数和第七种那个注册一样
BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Dog.class).getBeanDefinition();
beanDefinitionRegistry.registerBeanDefinition("yellow",beanDefinition);
}
@Override
public 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 {
@Override
public 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 {
@Override
public 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 {
//第一个参数就是我们之前看的元数据,而且他还有一个参数,也就是这种方式比第六种更强大
@Override
public 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 {
//第一个参数就是我们之前看的元数据,而且他还有一个参数,也就是这种方式比第六种更强大
@Override
public 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 {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
//后处理bean 定义注册,参数和第七种那个注册一样
BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl4.class).getBeanDefinition();
beanDefinitionRegistry.registerBeanDefinition("bookService",beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
}
这个加载的4 ,OK,终局之战
直接运行
MyPostProcessor说了算
这就是“后” 的意义,前面的全整完之后,我一来,前面的全部没用 了
【这种后处理的机制有什么用?】
保障性工作
这就是它最牛的地方
OK,回顾一下
导入实现了BeanDefinitionRegistryPostProcessor接口的类,通过BeanDefinition的注册器注册实名bean,
实现对容器中bean的最终裁定
其实还有加载方式,但是这些够用了
1.10.2 小结
- xml+<bean/>
- xml:context+注解(@Component+4个@Bean)
- 配置类+扫描+注解(@Component+4个@Bean)
- @Bean定义FactoryBean接口
- @ImportResource
- @Configuration注解的proxyBeanMethods属性
- @Import导入bean的类
- @Import导入配置类
- AnnotationConfigApplicationContext调用register方法
- @Import导入ImportSelector接口
- @Import导入ImportBeanDefinitionRegistrar接口
- @Import导入BeanDefinitionRegistryPostProcessor接口