常见工厂后处理器
A05Application.java
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
//dataSource
System.out.println(name);
}
//销毁容器
context.close();
}
}
Config.java
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 {
@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://localhost:3306/test");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
}
Bean1.java
java
package com.lucifer.itheima.a05;
public class Bean1 {
}
Bean2.java
java
package com.lucifer.itheima.a05.component;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Bean2 {
public Bean2(){
log.info("我被 Spring 管理啦");
}
}
Mapper1.java
java
package com.lucifer.itheima.a05.mapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface Mapper1 {
}
Mapper2.java
java
package com.lucifer.itheima.a05.mapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface Mapper2 {
}
工厂后处理器模拟实现-组件扫描1
A05Application.java
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.component
System.out.println(p);
//com.lucifer.itheima.a05.component -> classpath*:com/lucifer/itheima/a05/component/**/*.class
String path = "classpath*:" + p.replace(".","/") + "/**/*.class";
//输出结果为
//classpath*:com/lucifer/itheima/a05/component/**/*.class
System.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
//dataSource
System.out.println(name);
}
//销毁容器
context.close();
}
}
Bean2.java
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
java
package com.lucifer.itheima.a05.component;
import org.springframework.stereotype.Controller;
@Controller
public class Bean4 {
}
工厂后处理器模拟实现-组件扫描2
A05Application.java
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
//dataSource
System.out.println(name);
}
//销毁容器
context.close();
}
}
ComponentScanPostProcessor.java
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.component
System.out.println(p);
//com.lucifer.itheima.a05.component -> classpath*:com/lucifer/itheima/a05/component/**/*.class
String path = "classpath*:" + p.replace(".","/") + "/**/*.class";
//输出结果为
//classpath*:com/lucifer/itheima/a05/component/**/*.class
System.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
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
//dataSource
System.out.println(name);
}
//销毁容器
context.close();
}
}
AtBeanPostProcessor.java
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 {
@Override
public 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
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); //解析@Bean
context.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
//dataSource
System.out.println(name);
}
//销毁容器
context.close();
}
}
MapperPostProcessor.java
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 {
@Override
public 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();
}
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}