目录
一、BeanFactory和ApplicationContext的区别
1、较为经典的容器,基于classpath 下xml格式的配置文件来创建
4、较为经典的容器,基于Java配置类来创建,用于web环境
AutowiredAnnotationBeanPostProcessor详解
1、ConfigurationClassPostProcessor后置处理器,用于解析@ComponentScan @Bean @Import @ImportResource注解
一、BeanFactory和ApplicationContext的区别
applicationContext继承于beanFactory,对beanFactory功能进行了扩展
二、ApplicationContext的能力
1、messageSource: 处理国际化资源的能力,支持多种语言
2、resourcePatternResolver: 通配符匹配资源(磁盘路径/类路径找到的文件)的能力
3、applicationEventPublisher: 发布事件对象
4、environmentCapable: 读取系统环境变量(*.properties, *.yml)
三、beanFactory容器实现
1、beanFactory后置处理器主要功能:补充了一些bean定义,例如@Configration、@Bean
2、bean后置处理器,针对bean的生命周期的各个阶段提供扩展,例如@Autowired @Resource
小结:
1、beanFactory不会做的事
1、不会主动调用BeanFactory后处理器
2、不会主动添加Bean后处理器
3、不会主动初始化单例(用到的时候才会加载)
4、不会解析beanFactory 还不会解析${}和#{}
2、bean 后处理器会有排序的逻辑
1、@Autowire注解是按照类型注入,如一个接口存在两个相同的实现类(且属性名与任何一个实现类不同),此时按照类型注入会报错
- 根据属性名去匹配,当前要注入的属性名和哪个实现类同名,则注入哪个实现类
2、@Resorce是按照名字去找,若没有同名的则按照类型去找
- 可以在注解中添加属性name,按照哪个值去找
3、如果@Autowire和@Resorce同时存在,则@Autowire会先生效,因为@Autowire的后置处理器先被执行,如果重新调整两个注解的处理器,则生效顺序不同
(以上功能,applicationContext都会帮助我们做好)
四、ApplicationContext实现
1、较为经典的容器,基于classpath 下xml格式的配置文件来创建
能从xml中读取bean,主要是XmlBeanDefinitionReader发挥作用,原理如下:
2、基于磁盘路径下的xml格式的配置文件
原理同1
3、较为经典的容器,基于Java配置类来创建
4、较为经典的容器,基于Java配置类来创建,用于web环境
五、bean的生命周期
package A13;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
* @author shanshan.wang
* @since 2023/2/1 19:24
*/
@Component
@Data
public class LifeCycleBean {
private static final Logger log = LoggerFactory.getLogger(LifeCycleBean.class);
/**
* 方法执行顺序
* 1、构造方法
* 2、依赖注入
* 3、初始化
* 4、销毁(bean是单例时调用,其他类型的调用时间不同 )
*/
@Autowired
public void autowire(@Value("${JAVA_HOME}") String home) {
// 当参数是实体对象时,会根据类型进行注入
// 当参数是String类型时,不会主动进行注入,需要加@Value注解
log.info("依赖注入:{}", home);
}
@PostConstruct
public void init() {
log.info("初始化");
}
@PreDestroy
public void destroy() {
log.info("销毁");
}
}
package A13;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;
/**
* @author shanshan.wang
* @since 2023/2/2 10:27
*/
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
private static final Logger log = LoggerFactory.getLogger(MyBeanPostProcessor.class);
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")) {
log.info("销毁之前执行,如@PreDestory");
}
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")) {
log.info("实例化之前执行,这里会返回的对象会替换掉原本的bean");
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")) {
log.info("实例化之后执行,这里如果返回false会跳过依赖注入阶段");
}
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")) {
log.info("依赖注入阶段执行,如@Autowired、@Value、@Resource");
}
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")) {
log.info("初始化之前执行,这里返回的对象会替换掉原本的bean,如@PostConstruct、@ConfigurationProperties");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("lifeCycleBean")) {
log.info("初始化之后执行,这里返回的对象会替换掉原本的bean,如代理增强");
}
return bean;
}
}
执行结果:
六、Bean后处理器(为Bean生命周期各个阶段提供扩展)
各个处理器执行时机
- AutowiredAnnotationBeanPostProcessor:解析@Autowired 依赖注入阶段执行
- CommonAnnotationBeanPostProcessor:
- @Resource:依赖注入阶段
- @PostConstruct:初始化前(虽然名字叫实例化后)
- @PreDestroy:销毁前
- ConfiguraPropertiesBindingPostProcessor:解析@ConfigurationProperties 初始化前
package A15;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.context.support.GenericApplicationContext;
/**
* @author shanshan.wang
* @since 2023/2/3 10:31
*/
public class Application {
public static void main(String[] args) {
// GenericApplicationContext 是一个干净的容器(其中无任何bean工厂处理器,bean处理器,像AnnotationConfigApplicationContext这个容器中就已经提前放好了beanFactory后置处理器)
GenericApplicationContext context = new GenericApplicationContext();
// 使用原始方法注册三个bean
context.registerBean("bean1", Bean1.class);
context.registerBean("bean2", Bean2.class);
context.registerBean("bean3", Bean3.class);
// new ContextAnnotationAutowireCandidateResolver() 能够解析@Value注解
context.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
// 解析@Autowired注解
context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
// 解析@Resource @PostConstruct @PreDestroy(容器关闭时,改注解才被解析执行单例销毁)
context.registerBean(CommonAnnotationBeanPostProcessor.class);
// 解析@ConfigurationProperties
ConfigurationPropertiesBindingPostProcessor.register(context.getDefaultListableBeanFactory());
// 初始化器
// 执行BeanFactory后处理器,添加bean后置处理器,初始化所有单例
context.refresh();
// 销毁容器
context.close();
}
}
package A15;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
/**
* @author shanshan.wang
* @since 2023/2/3 10:33
*/
@Data
public class Bean1 {
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
private Bean2 bean2;
private Bean3 bean3;
private String home;
/**
* 一般注解都会放在属性上
* 这里之所以都放在方法上是因为这样可以清楚的将信息打印出来
* 方便了解,bean是否注入成功
*/
@Autowired
public void setBean2(Bean2 bean2) {
log.info("@Autowired 生效:{}", bean2);
this.bean2 = bean2;
}
@Resource
public void setBean3(Bean3 bean3) {
log.info("@Resource 生效:{}", bean3);
this.bean3 = bean3;
}
@Autowired
public void autowire(@Value("${java.home:666}") String home) {
// 当参数是实体对象时,会根据类型进行注入
// 当参数是String类型时,不会主动进行注入,需要加@Value注解
log.info("@Value 生效:{}", home);
}
@PostConstruct
public void init() {
log.info("@PostConstruct 生效");
}
@PreDestroy
public void destroy() {
log.info("@PreDestroy 生效");
}
}
package A15;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author shanshan.wang
* @since 2023/2/3 10:34
*/
@Data
@ConfigurationProperties(prefix = "java", ignoreInvalidFields = true)
public class Bean2 {
private String name;
private String home;
}
AutowiredAnnotationBeanPostProcessor详解
package A17;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
/**
* @author shanshan.wang
* @since 2023/2/3 15:53
*/
public class Application {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 将对象放到spring容器中
// registerSingleton只需要提供bean名称及bean实例,缺点是这个bean是直接new出来放到容器中
// spring认为这是一个完整的bean,不会再去走创建流程、依赖注入、初始化等
beanFactory.registerSingleton("bean2", new Bean2());
beanFactory.registerSingleton("bean3", new Bean3());
// 解析@Value注解
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
// 获取后置处理器对象
// 正常情况下,后置处理器会在依赖注入阶段被调用,执行bean的属性赋值
AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
beanPostProcessor.setBeanFactory(beanFactory);
Bean1 bean1 = new Bean1();
System.out.println(bean1); //Bean1(bean2=null, bean3=null, home=null)
// 执行后置处理器,为属性赋值
beanPostProcessor.postProcessProperties(null, bean1, "bean1");
System.out.println(bean1); //Bean1(bean2=Bean2(name=null, home=null), bean3=null, home=null)
}
}
1、其中主要起作用的方法为beanPostProcessor.postProcessProperties(PropertyValues pvs, Object bean, String beanName)
- 第一个参数为自己指定实体对象中每个属性注入什么值,而不用spring自动装配模式
- 第二个参数为被注入的目标
- 第三个参数为bean名称
该方法主要有两个功能:
- findAutowiringMetadata 获取加了@Autowired的属性及方法、
- metadata.inject用反射给属性赋值,反射调用set方法
2、模拟源码原理
package A17;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.MethodParameter;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;
/**
* @author shanshan.wang
* @since 2023/2/3 15:53
*/
public class Application {
public static void main(String[] args) throws Throwable {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 将对象放到spring容器中
// registerSingleton只需要提供bean名称及bean实例,缺点是这个bean是直接new出来放到容器中
// spring认为这是一个完整的bean,不会再去走创建流程、依赖注入、初始化等
beanFactory.registerSingleton("bean2", new Bean2());
beanFactory.registerSingleton("bean3", new Bean3());
// 解析@Value注解
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
// 获取后置处理器对象
// 正常情况下,后置处理器会在依赖注入阶段被调用,执行bean的属性赋值
AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
beanPostProcessor.setBeanFactory(beanFactory);
Bean1 bean1 = new Bean1();
System.out.println(bean1); //Bean1(bean2=null, bean3=null, home=null)
// // 执行后置处理器,为属性赋值
// beanPostProcessor.postProcessProperties(null, bean1, "bean1");
// System.out.println(bean1); //Bean1(bean2=Bean2(name=null, home=null), bean3=null, home=null)
// 模拟postProcessProperties方法开始》》》》》》》》》》》
// 1、反射调用方法获取加了注解的属性&&方法
Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
findAutowiringMetadata.setAccessible(true);
InjectionMetadata metadata = (InjectionMetadata)findAutowiringMetadata.invoke(beanPostProcessor, "bean1", Bean1.class, null);
// 获取到了加了@Autowired注解的setBean2和autowire方法 及 加了@Autowired注解的bean3属性
System.out.println(metadata);
// 2、调用metadata.inject方法进行依赖注入,注入时按类型查找值
metadata.inject(bean1, "bean1", null);
System.out.println(bean1);
// 《《《《《《《《《模拟postProcessProperties方法结束
// 对metadata.inject方法解析开始》》》》》》》》
// 1、属性注入
Field bean3 = Bean1.class.getDeclaredField("bean3");
// 1.1设置为false,如果容器中没有找到对应的对象不会报错
DependencyDescriptor descriptor = new DependencyDescriptor(bean3, false);
// 1.2根据成员变量类型去找要注入谁
Object o = beanFactory.doResolveDependency(descriptor, "bean3", null, null);
// 1.3 将找到的对象通过反射赋值给对应的属性
// 2、方法注入
Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
// 对于方法而言,一个方法对应多个DependencyDescriptor对象,因为一个方法可能注入多个参数
DependencyDescriptor descriptor1 = new DependencyDescriptor(new MethodParameter(setBean2, 0), false);
beanFactory.doResolveDependency(descriptor1, null, null, null);
// 《《《《《《《《对metadata.inject方法解析结束
}
}
七、BeanFactory后置处理器
1、ConfigurationClassPostProcessor后置处理器,用于解析@ComponentScan @Bean @Import @ImportResource注解
package A19;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
/**
* @author shanshan.wang
* @since 2023/2/7 20:42
*/
public class Application {
public static void main(String[] args) {
// GenericApplicationContext 是一个干净的容器(其中无任何bean工厂处理器,bean处理器,像AnnotationConfigApplicationContext这个容器中就已经提前放好了beanFactory后置处理器)
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("config", Config.class);
// 解析@ComponentScan @Bean @Import @ImportResource注解
context.registerBean(ConfigurationClassPostProcessor.class);
// 解析@Mapper注解,需要指定要扫描的包
context.registerBean(MapperScannerConfigurer.class, beanDefinition -> beanDefinition.getPropertyValues().add("basePackage", "A19.mapper"));
// 初始化器
// 执行BeanFactory后处理器,添加bean后置处理器,初始化所有单例
context.refresh();
for (String name : context.getBeanDefinitionNames()) {
System.out.println(name);
}
// 销毁容器
context.close();
}
}
package A19;
import A19.bean.Bean1;
import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
* @author shanshan.wang
* @since 2023/2/7 20:27
*/
@Configuration
@ComponentScan
public class Config {
@Bean
public Bean1 bean1() {
return new Bean1();
}
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
@Bean(initMethod = "init")
public DruidDataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://mysql.jidudev.com:3306/jidu_business_order?zeroDateTimeBehavior=convertToNull&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&useSSL=false&allowMultiQueries=true");
dataSource.setUsername("bus_order_wr");
dataSource.setPassword("qE4dA0oR7b");
return dataSource;
}
}
package A19.bean;
/**
* @author shanshan.wang
* @since 2023/2/7 21:10
*/
public class Bean1 {
}
===============================
package A19.bean;
import A17.Bean1;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
/**
* @author shanshan.wang
* @since 2023/2/7 20:31
*/
@Controller
public class Bean2 {
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
public Bean2() {
log.info("我是Bean2, 我被spring管理了....");
}
}
============================================
package A19.bean;
import A17.Bean1;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* @author shanshan.wang
* @since 2023/2/7 20:31
*/
@Component
public class Bean3 {
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
public Bean3() {
log.info("我是Bean3, 我被spring管理啦...");
}
}
===================================
package A19.bean;
import A17.Bean1;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author shanshan.wang
* @since 2023/2/7 20:31
*/
public class Bean4 {
private static final Logger log = LoggerFactory.getLogger(Bean1.class);
public Bean4() {
log.info("我是Bean4, 我被spring管理啦...");
}
}
模拟源码,解析@ComponentScan注解
- 判断类上是否有@Component注解
- 将注解的属性值替换为类路径
- 根据类路径从容器中获取到对应的资源
- 根据资源从容器中拿到类元信息
- 判断类上是否加了@Component注解 或者 间接加了@Component注解
- 为每个类生成beanDefinition对象
- 将bean放到容器中
package A19;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;
import java.io.IOException;
/**
* @author shanshan.wang
* @since 2023/2/7 20:42
*/
public class Application {
public static void main(String[] args) throws IOException {
// GenericApplicationContext 是一个干净的容器(其中无任何bean工厂处理器,bean处理器,像AnnotationConfigApplicationContext这个容器中就已经提前放好了beanFactory后置处理器)
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("config", Config.class);
// // 解析@ComponentScan @Bean @Import @ImportResource注解
// context.registerBean(ConfigurationClassPostProcessor.class);
// // 解析@Mapper注解,需要指定要扫描的包
// context.registerBean(MapperScannerConfigurer.class, beanDefinition -> beanDefinition.getPropertyValues().add("basePackage", "A19.mapper"));
// 模拟解析@ComponentScan注解开始》》》》》》》》》
// 查看类上是否有@ComponentScan注解
ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
if (componentScan != null) {
// 说明类上有@ComponentScan注解
// 获取到注解上的basePackages内容
String[] packages = componentScan.basePackages();
for (String pac :packages){
// 将获取到的属性值替换为类路径
String path = "classpath*:" + pac.replace(".", "/") + "/**/*.class";
// 从容器中根据类路径获取到类信息
Resource[] resources = context.getResources(path);
// 元信息读取工厂
CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
// 用于获取bean名称(For example: com.xyz.FooServiceImpl -> fooServiceImpl)
AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
for (Resource resource : resources) {
// 获取到对应资源的元信息
MetadataReader metadataReader = factory.getMetadataReader(resource);
// 获取到资源上所加注解的相关数据
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
// 判断是否有@Component注解 或者 间接加了@Component注解
if (annotationMetadata.hasAnnotation(Component.class.getName()) || annotationMetadata.hasMetaAnnotation(Component.class.getName())) {
// 获取beanDefinition对象
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName()).getBeanDefinition();
DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();
// 获取bean名称
String beanName = generator.generateBeanName(beanDefinition, beanFactory);
// 将bean放到容器中
beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
}
}
}
// 模拟解析@ComponentScan注解结束《《《《《《《《《《《《《《《《
// 初始化器
// 执行BeanFactory后处理器,添加bean后置处理器,初始化所有单例
context.refresh();
for (String name : context.getBeanDefinitionNames()) {
System.out.println(name);
}
// 销毁容器
context.close();
}
}
将模拟代码抽取出后置处理器
这部分的调整是因为之前直接从上下文中根据路径查找对应的资源,现阶段是bean工厂后置处理器,当前并不知道上下文是什么,所以换一种方式获取
package A19;
import lombok.SneakyThrows;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;
/**
* @author shanshan.wang
* @since 2023/2/9 10:35
*/
public class ComponentScanProcessor implements BeanFactoryPostProcessor {
@SneakyThrows
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
if (componentScan != null) {
// 说明类上有@ComponentScan注解
// 获取到注解上的basePackages内容
String[] packages = componentScan.basePackages();
for (String pac :packages){
// 将获取到的属性值替换为类路径
String path = "classpath*:" + pac.replace(".", "/") + "/**/*.class";
// 从容器中根据类路径获取到类信息
Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
// 用于获取bean名称(For example: com.xyz.FooServiceImpl -> fooServiceImpl)
AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
for (Resource resource : resources) {
// 获取到类元信息
MetadataReader metadataReader = factory.getMetadataReader(resource);
// 获取到类上所加注解的相关数据
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
// 判断是否有@Component注解 或者 间接加了@Component注解
if (annotationMetadata.hasAnnotation(Component.class.getName()) || annotationMetadata.hasMetaAnnotation(Component.class.getName())) {
// 获取beanDefinition对象
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName()).getBeanDefinition();
if (configurableListableBeanFactory instanceof DefaultListableBeanFactory) {
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
// 获取bean名称
String beanName = generator.generateBeanName(beanDefinition, beanFactory);
// 将bean放到容器中
beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
}
}
}
}
}
}
package A19;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;
import java.io.IOException;
/**
* @author shanshan.wang
* @since 2023/2/7 20:42
*/
public class Application {
public static void main(String[] args) throws IOException {
// GenericApplicationContext 是一个干净的容器(其中无任何bean工厂处理器,bean处理器,像AnnotationConfigApplicationContext这个容器中就已经提前放好了beanFactory后置处理器)
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("config", Config.class);
// // 解析@ComponentScan @Bean @Import @ImportResource注解
// context.registerBean(ConfigurationClassPostProcessor.class);
// // 解析@Mapper注解,需要指定要扫描的包
// context.registerBean(MapperScannerConfigurer.class, beanDefinition -> beanDefinition.getPropertyValues().add("basePackage", "A19.mapper"));
context.registerBean(ComponentScanProcessor.class);
// 初始化器
// 执行BeanFactory后处理器,添加bean后置处理器,初始化所有单例
context.refresh();
for (String name : context.getBeanDefinitionNames()) {
System.out.println(name);
}
// 销毁容器
context.close();
}
}
2、MapperPostProcessor源码实现
1、spring底层加载mapper文件的方式
实际上加载到spring容器中的bean实际上
package A24;
import A19.bean.Bean1;
import A19.mapper.Mapper2;
import A24.mapper.Mapper1;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
* @author shanshan.wang
* @since 2023/2/7 20:27
*/
@Configuration
@ComponentScan("A19.bean")
public class Config {
@Bean
public Bean1 bean1() {
return new Bean1();
}
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
@Bean(initMethod = "init")
public DruidDataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://mysql.jidudev.com:3306/jidu_business_order?zeroDateTimeBehavior=convertToNull&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useLegacyDatetimeCode=false&useSSL=false&allowMultiQueries=true");
dataSource.setUsername("bus_order_wr");
dataSource.setPassword("qE4dA0oR7b");
return dataSource;
}
public MapperFactoryBean<Mapper1> mapper1(SqlSessionFactory sqlSessionFactory) {
// spring 容器中实际上注入的是MapperFactoryBean类型的实体,而非具体的Mapper
MapperFactoryBean<Mapper1> factory = new MapperFactoryBean<>(Mapper1.class);
factory.setSqlSessionFactory(sqlSessionFactory);
return factory;
}
public MapperFactoryBean<Mapper2> mapper2(SqlSessionFactory sqlSessionFactory) {
MapperFactoryBean<Mapper2> factory = new MapperFactoryBean<>(Mapper2.class);
factory.setSqlSessionFactory(sqlSessionFactory);
return factory;
}
}