当前位置: 首页 > news >正文

Spring底层原理学习笔记--第五讲--(常见工厂后处理器与工厂后处理器模拟实现)

常见工厂后处理器

A05Application.java

package com.lucifer.itheima.a05;import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.stereotype.Component;@Component
public class A05Application {public static void main(String[] args) {// GenericApplicationContext是一个【干净】的容器GenericApplicationContext context = new GenericApplicationContext();context.registerBean("config",Config.class);context.registerBean(ConfigurationClassPostProcessor.class);  //能解析@Component @Bean @Import @ImportResource注解context.registerBean(MapperScannerConfigurer.class,bd->{  // 能解析@MapperScanner注解bd.getPropertyValues().add("basePackage","com.lucifer.itheima.a05.mapper");});// 初始化容器context.refresh();for (String name:context.getBeanDefinitionNames()){//没有加        context.registerBean(ConfigurationClassPostProcessor.class);的话//输出结果为//config(只有一个bean,也就是Config类中的组件扫描没有生效,Config类中的三个@Bean也没有生效)// 加上         context.registerBean(ConfigurationClassPostProcessor.class);的话//输出结果为//bean2//bean1//sqlSessionFactoryBean//dataSourceSystem.out.println(name);}//销毁容器context.close();}}

Config.java

package com.lucifer.itheima.a05;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;@Configuration
@ComponentScan("com.lucifer.itheima.a05.component")
public class Config {@Beanpublic Bean1 bean1(){return new Bean1();}@Beanpublic 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://localhost:3306/test");dataSource.setUsername("root");dataSource.setPassword("root");return dataSource;}
}

Bean1.java

package com.lucifer.itheima.a05;public class Bean1 {
}

Bean2.java

package com.lucifer.itheima.a05.component;import lombok.extern.slf4j.Slf4j;@Slf4j
public class Bean2 {public Bean2(){log.info("我被 Spring 管理啦");}
}

Mapper1.java

package com.lucifer.itheima.a05.mapper;import org.apache.ibatis.annotations.Mapper;@Mapper
public interface Mapper1 {
}

Mapper2.java

package com.lucifer.itheima.a05.mapper;import org.apache.ibatis.annotations.Mapper;@Mapper
public interface Mapper2 {
}

工厂后处理器模拟实现-组件扫描1

A05Application.java

package com.lucifer.itheima.a05;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.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;import java.io.IOException;@Component
public class A05Application {public static void main(String[] args) throws IOException {// GenericApplicationContext是一个【干净】的容器GenericApplicationContext context = new GenericApplicationContext();context.registerBean("config",Config.class);
//        context.registerBean(ConfigurationClassPostProcessor.class);  //能解析@Component @Bean @Import @ImportResource注解
//        context.registerBean(MapperScannerConfigurer.class,bd->{  // 能解析@MapperScanner注解
//            bd.getPropertyValues().add("basePackage","com.lucifer.itheima.a05.mapper");
//        });ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class,ComponentScan.class);if (componentScan != null) {for (String p:componentScan.basePackages()) {// 输出结果为//com.lucifer.itheima.a05.componentSystem.out.println(p);//com.lucifer.itheima.a05.component -> classpath*:com/lucifer/itheima/a05/component/**/*.classString path = "classpath*:" + p.replace(".","/") + "/**/*.class";//输出结果为//classpath*:com/lucifer/itheima/a05/component/**/*.classSystem.out.println(path);CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();//CachingMetadataReaderFactory可以遍历类的原信息Resource[] resources = context.getResources(path);for (Resource resource : resources){// 输出结果为 file [E:\Project\target\classes\com\lucifer\itheima\a05\component\Bean2.class]System.out.println(resource);MetadataReader reader = factory.getMetadataReader(resource);//会去读取我们的每一个class,这里是Bean2.class//输出结果为
//                    类名:com.lucifer.itheima.a05.component.Bean2
//                    是否加了 @Component:true
//                    是否加了 @Component派生注解:false
//                    类名:com.lucifer.itheima.a05.component.Bean4
//                    是否加了 @Component:false
//                    是否加了 @Component派生注解:true// reader里可以拿到类的一些注解或名字啥的System.out.println("类名:"+reader.getClassMetadata().getClassName()); //reader.getClassMetadata// 会得到类的元信息System.out.println("是否加了 @Component:" + reader.getAnnotationMetadata().hasAnnotation(Component.class.getName()));System.out.println("是否加了 @Component派生注解:" + reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));}}}// 初始化容器context.refresh();for (String name:context.getBeanDefinitionNames()){//没有加        context.registerBean(ConfigurationClassPostProcessor.class);的话//输出结果为//config(只有一个bean,也就是Config类中的组件扫描没有生效,Config类中的三个@Bean也没有生效)// 加上         context.registerBean(ConfigurationClassPostProcessor.class);的话//输出结果为//bean2//bean1//sqlSessionFactoryBean//dataSourceSystem.out.println(name);}//销毁容器context.close();}}

Bean2.java

package com.lucifer.itheima.a05.component;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;@Slf4j
@Component
public class Bean2 {public Bean2(){log.info("我被 Spring 管理啦");}
}

Bean4.java

package com.lucifer.itheima.a05.component;import org.springframework.stereotype.Controller;@Controller
public class Bean4 {
}

工厂后处理器模拟实现-组件扫描2

A05Application.java

package com.lucifer.itheima.a05;import org.springframework.context.support.GenericApplicationContext;
import org.springframework.stereotype.Component;import java.io.IOException;@Component
public class A05Application {public static void main(String[] args) throws IOException {// GenericApplicationContext是一个【干净】的容器GenericApplicationContext context = new GenericApplicationContext();context.registerBean("config",Config.class);
//        context.registerBean(ConfigurationClassPostProcessor.class);  //能解析@Component @Bean @Import @ImportResource注解
//        context.registerBean(MapperScannerConfigurer.class,bd->{  // 能解析@MapperScanner注解
//            bd.getPropertyValues().add("basePackage","com.lucifer.itheima.a05.mapper");
//        });context.registerBean(ComponentScanPostProcessor.class);// 初始化容器context.refresh();for (String name:context.getBeanDefinitionNames()){//没有加        context.registerBean(ConfigurationClassPostProcessor.class);的话//输出结果为//config(只有一个bean,也就是Config类中的组件扫描没有生效,Config类中的三个@Bean也没有生效)// 加上         context.registerBean(ConfigurationClassPostProcessor.class);的话//输出结果为//bean2//bean1//sqlSessionFactoryBean//dataSourceSystem.out.println(name);}//销毁容器context.close();}}

ComponentScanPostProcessor.java

package com.lucifer.itheima.a05;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;import java.io.IOException;public class ComponentScanPostProcessor implements BeanFactoryPostProcessor {@Override   //在context.refresh的时候会调用这个方法public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {try {ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);if (componentScan != null) {for (String p:componentScan.basePackages()) {// 输出结果为//com.lucifer.itheima.a05.componentSystem.out.println(p);//com.lucifer.itheima.a05.component -> classpath*:com/lucifer/itheima/a05/component/**/*.classString path = "classpath*:" + p.replace(".","/") + "/**/*.class";//输出结果为//classpath*:com/lucifer/itheima/a05/component/**/*.classSystem.out.println(path);CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();//CachingMetadataReaderFactory可以遍历类的原信息Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();for (Resource resource : resources){// 输出结果为 file [E:\Project\target\classes\com\lucifer\itheima\a05\component\Bean2.class]System.out.println(resource);MetadataReader reader = factory.getMetadataReader(resource);//会去读取我们的每一个class,这里是Bean2.class//输出结果为//                    类名:com.lucifer.itheima.a05.component.Bean2//                    是否加了 @Component:true//                    是否加了 @Component派生注解:false//                    类名:com.lucifer.itheima.a05.component.Bean4//                    是否加了 @Component:false//                    是否加了 @Component派生注解:true// reader里可以拿到类的一些注解或名字啥的System.out.println("类名:"+reader.getClassMetadata().getClassName()); //reader.getClassMetadata// 会得到类的元信息AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();System.out.println("是否加了 @Component:" + reader.getAnnotationMetadata().hasAnnotation(Component.class.getName()));System.out.println("是否加了 @Component派生注解:" + reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));if (annotationMetadata.hasAnnotation(Component.class.getName()) ||annotationMetadata.hasMetaAnnotation(Component.class.getName())) {AbstractBeanDefinition bd =BeanDefinitionBuilder.genericBeanDefinition(reader.getClassMetadata().getClassName()).getBeanDefinition();if (configurableListableBeanFactory instanceof DefaultListableBeanFactory beanFactory) {String name = generator.generateBeanName(bd, beanFactory);beanFactory.registerBeanDefinition(name,bd);}}}}}} catch (IOException e) {e.printStackTrace();}}
}

工厂后处理器模拟实现-@Bean

A05Application.java

package com.lucifer.itheima.a05;import org.springframework.context.support.GenericApplicationContext;
import org.springframework.stereotype.Component;import java.io.IOException;@Component
public class A05Application {public static void main(String[] args) throws IOException {// GenericApplicationContext是一个【干净】的容器GenericApplicationContext context = new GenericApplicationContext();context.registerBean("config",Config.class);
//        context.registerBean(ConfigurationClassPostProcessor.class);  //能解析@Component @Bean @Import @ImportResource注解
//        context.registerBean(MapperScannerConfigurer.class,bd->{  // 能解析@MapperScanner注解
//            bd.getPropertyValues().add("basePackage","com.lucifer.itheima.a05.mapper");
//        });//        context.registerBean(ComponentScanPostProcessor.class);context.registerBean(AtBeanPostProcessor.class);// 初始化容器context.refresh();for (String name:context.getBeanDefinitionNames()){//没有加        context.registerBean(ConfigurationClassPostProcessor.class);的话//输出结果为//config(只有一个bean,也就是Config类中的组件扫描没有生效,Config类中的三个@Bean也没有生效)// 加上         context.registerBean(ConfigurationClassPostProcessor.class);的话//输出结果为//bean2//bean1//sqlSessionFactoryBean//dataSourceSystem.out.println(name);}//销毁容器context.close();}}

AtBeanPostProcessor.java

package com.lucifer.itheima.a05;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.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;import java.io.IOException;
import java.util.Set;public class AtBeanPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {try {CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();MetadataReader reader = factory.getMetadataReader(new ClassPathResource("com/lucifer/itheima/a05/config" +".class"));Set<MethodMetadata> methods = reader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());for (MethodMetadata method:methods) {//输出结果为//            com.lucifer.itheima.a05.Config.bean1()//            com.lucifer.itheima.a05.Config.dataSource()System.out.println(method);String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();builder.setFactoryMethodOnBean(method.getMethodName(),"config");builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);if (initMethod.length()>0) {builder.setInitMethodName(initMethod);}AbstractBeanDefinition bd = builder.getBeanDefinition();if (configurableListableBeanFactory instanceof DefaultListableBeanFactory beanFactory) {beanFactory.registerBeanDefinition(method.getMethodName(),bd);}}} catch (IOException e) {e.printStackTrace();}}
}

工厂后处理器模拟实现-Mapper

A05Application.java

package com.lucifer.itheima.a05;import org.springframework.context.support.GenericApplicationContext;
import org.springframework.stereotype.Component;import java.io.IOException;@Component
public class A05Application {public static void main(String[] args) throws IOException {// GenericApplicationContext是一个【干净】的容器GenericApplicationContext context = new GenericApplicationContext();context.registerBean("config",Config.class);
//        context.registerBean(ConfigurationClassPostProcessor.class);  //能解析@Component @Bean @Import @ImportResource注解
//        context.registerBean(MapperScannerConfigurer.class,bd->{  // 能解析@MapperScanner注解
//            bd.getPropertyValues().add("basePackage","com.lucifer.itheima.a05.mapper");
//        });//        context.registerBean(ComponentScanPostProcessor.class);  //解析@ComponentScan
//        context.registerBean(AtBeanPostProcessor.class);  //解析@Beancontext.registerBean(MapperPostProcessor.class);   //解析Mapper接口// 初始化容器context.refresh();for (String name:context.getBeanDefinitionNames()){//没有加        context.registerBean(ConfigurationClassPostProcessor.class);的话//输出结果为//config(只有一个bean,也就是Config类中的组件扫描没有生效,Config类中的三个@Bean也没有生效)// 加上         context.registerBean(ConfigurationClassPostProcessor.class);的话//输出结果为//bean2//bean1//sqlSessionFactoryBean//dataSourceSystem.out.println(name);}//销毁容器context.close();}}

MapperPostProcessor.java

package com.lucifer.itheima.a05;import org.checkerframework.checker.units.qual.A;
import org.mybatis.spring.mapper.MapperFactoryBean;
import org.springframework.beans.BeansException;
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.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;import java.io.IOException;public class MapperPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {try {PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();Resource[] resources = resolver.getResources("classpath:com/lucifer/itheima/a05/mapper/**/*.class");AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();for (Resource resource:resources){MetadataReader reader = factory.getMetadataReader(resource);ClassMetadata classMetadata = reader.getClassMetadata();if (classMetadata.isInterface()) {AbstractBeanDefinition bd =BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class).addConstructorArgValue(classMetadata.getClassName()).setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE).getBeanDefinition();AbstractBeanDefinition bd2 = BeanDefinitionBuilder.genericBeanDefinition(classMetadata.getClassName()).getBeanDefinition();String name = generator.generateBeanName(bd2,beanFactory);beanFactory.registerBeanDefinition(name,bd);}}} catch (IOException e) {e.printStackTrace();}}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}

相关文章:

  • Sass 最基础的语法
  • Maven-依赖管理机制
  • 【大数据分布并行处理】单元测试(三)
  • CMOS介绍
  • [HXPCTF 2021]includer‘s revenge
  • MYSQL---基础篇
  • 4.HTML网页开发的工具
  • Clickhouse学习笔记(11)—— 数据一致性
  • ELK分布式日志
  • TypeScript: 判断两个数组的内容是否相等
  • 解决游戏找不到x3daudio1_7.dll文件的5个方法,快速修复dll问题
  • Ubuntu 20.04编译Chrome浏览器
  • 『MySQL快速上手』-⑤-数据类型
  • 使用微信小程序控制蓝牙小车(微信小程序端)
  • U盘插在电脑上显示要格式化磁盘怎么办
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • 2017 年终总结 —— 在路上
  • C++11: atomic 头文件
  • chrome扩展demo1-小时钟
  • js对象的深浅拷贝
  • js中的正则表达式入门
  • Linux中的硬链接与软链接
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • 初识 beanstalkd
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 将 Measurements 和 Units 应用到物理学
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • 算法---两个栈实现一个队列
  • 我是如何设计 Upload 上传组件的
  • 用jquery写贪吃蛇
  • 在electron中实现跨域请求,无需更改服务器端设置
  • linux 淘宝开源监控工具tsar
  • ​批处理文件中的errorlevel用法
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • %check_box% in rails :coditions={:has_many , :through}
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (1)STL算法之遍历容器
  • (13)Hive调优——动态分区导致的小文件问题
  • (C)一些题4
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (第27天)Oracle 数据泵转换分区表
  • (二)springcloud实战之config配置中心
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (力扣)1314.矩阵区域和
  • (十三)Maven插件解析运行机制
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .cfg\.dat\.mak(持续补充)
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例
  • .NET Framework .NET Core与 .NET 的区别
  • .NET MVC 验证码
  • .net refrector
  • .NET/C# 判断某个类是否是泛型类型或泛型接口的子类型
  • @LoadBalanced 和 @RefreshScope 同时使用,负载均衡失效分析