栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring-黑马

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring-黑马

1. BeanFactory-获取单例Bean

BeanFactory能干点啥? -表面上只有getBean -实际上控制反转,基本的依赖注入,直至Bean的生命周期的各种功能,都由它的实现类提供

DefaultSingletonBeanRegistry : 保存容器中的单例Bean Map

@SpringBootApplication
@Slf4j
public class SpringdemoPraApplication {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        ConfigurableApplicationContext context = SpringApplication.run(SpringdemoPraApplication.class, args);
        log.info("BeanFactory => {} ",context);



        Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
        singletonObjects.setAccessible(true);
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        Map beanSingleObject = (Map) singletonObjects.get(beanFactory);
       // beanSingleObject.forEach((k,v) -> log.info("{} ::: {}",k,v));

        beanSingleObject.entrySet().
                stream().
                filter(e -> e.getKey().startsWith("component")).
                forEach(e -> log.info("{} ::: {}",e.getKey(),e.getValue()));
    }
}

java.lang.reflect.Field.get(Object obj)方法返回指定对象上由此Field表示的字段的值。如果该对象具有原始类型,则该值将自动包装在对象中。 //更多请阅读:https://www.yiibai.com/javareflect/javareflect_field_get.html

2.ApplicationContext功能 2.1 MessageSource

提供国际化(对应语言翻译)的能力

@SpringBootApplication
@Slf4j
public class SpringdemoPraApplication {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        ConfigurableApplicationContext context = SpringApplication.run(SpringdemoPraApplication.class, args);

        log.info("En_Translate Hi => {} " ,  context.getMessage("hi",null, Locale.ENGLISH));
        log.info("Ja_Translate Hi => {} " ,  context.getMessage("hi",null, Locale.JAPANESE));
        log.info("Zh_Translate Hi => {} " ,  context.getMessage("hi",null, Locale.CHINESE));

    }
}
2.2 ResourcePatternResolver

通配符获取资源

@SpringBootApplication
@Slf4j
public class SpringdemoPraApplication {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        ConfigurableApplicationContext context = SpringApplication.run(SpringdemoPraApplication.class, args);

        Resource[] resources = context.getResources("classpath*:application.yml");
        for (Resource resource : resources) {
            log.info("resource => {}",resource);
        }
    }
}
2.3 EnvironmentCapable

获取配置信息或者环境变量

@SpringBootApplication
@Slf4j
public class SpringdemoPraApplication {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        ConfigurableApplicationContext context = SpringApplication.run(SpringdemoPraApplication.class, args);

        String java_home = context.getEnvironment().getProperty("JAVA_HOME");
        log.info("java_home => {}",java_home);
        String server_port = context.getEnvironment().getProperty("server.port");
        log.info("server.port => {}",server_port);
    }
}
2.4 ApplicationEventPublisher

事件发布 , 用于Bean之间的解耦

事件源

public class UserRegisterEventPublisher extends ApplicationEvent {
    
    public UserRegisterEventPublisher(Object source) {
        super(source);
    }
}

发布事件

@SpringBootApplication
@Slf4j
public class SpringdemoPraApplication {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {

        ConfigurableApplicationContext context = SpringApplication.run(SpringdemoPraApplication.class, args);

        context.publishEvent(new UserRegisterEventPublisher(context));
    }
}

监听器-Email : 任何 Bean 都可以接收事件

@Component
@Slf4j
public class UserRegEmail {

    @EventListener
    public void registerByEmail(UserRegisterEventPublisher eventPublisher){
        log.info("收到事件 执行发邮件进行用户注册");
    }
}

监听器-SMS: 任何 Bean 都可以接收事件

@Component
@Slf4j
public class UserRegSMS {

    @EventListener
    public void registerBySMS(UserRegisterEventPublisher eventPublisher){
        log.info("收到事件 执行发短信进行用户注册");
    }
}

3.BeanFactory实现 3.1 后置处理器

BeanFactoryBeanPostProcessor : 添加BeanFactory的后处理 , 来给beanFactory增添解析注解的能力 @Configuration , @Bean

BeanBeanPostProcessor : 添加Bean的后处理 , 来给beanFactory增添增强生命周期增强的方法 , 可以进行依赖注入 , 能够解析 @Autowired , @Resources

  • beanDefinitionName => org.springframework.context.annotation.internalConfigurationAnnotationProcessor

    • beanFactory的后置处理器 , 添加解析@Configuration , @Bean的能力

  • beanDefinitionName => org.springframework.context.annotation.internalAutowiredAnnotationProcessor

    • bean后置处理器 , 添加解析 @Autowired的能力

  • beanDefinitionName => org.springframework.context.annotation.internalCommonAnnotationProcessor

    • bean后置处理器 , 添加解析 @Resoureces的能力

  • beanDefinitionName => org.springframework.context.event.internalEventListenerProcessor

  • beanDefinitionName => org.springframework.context.event.internalEventListenerFactory

public class TestBeanFactory {
    public static void main(String[] args) {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(SpringConfig.class).setScope("singleton").getBeanDefinition();
        beanFactory.registerBeanDefinition("beanDefinition",beanDefinition);
		//添加beanFactory的处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

        //beanFactoryPostProcessor
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).
                values().
                forEach(beanFactoryPostProcessor -> beanFactoryPostProcessor.postProcessBeanFactory(beanFactory));

        //beanPostProcessor
        beanFactory.getBeansOfType(BeanPostProcessor.class).
                values().
                forEach(beanPostProcessor -> beanFactory.addBeanPostProcessor(beanPostProcessor));

        BeanOne beanOne = beanFactory.getBean(BeanOne.class);

        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.err.println("beanDefinitionName => " + beanDefinitionName);
        }

        //饿加载
        beanFactory.preInstantiateSingletons();
        
        System.err.println("beanTwo => " + beanOne.getBeanTwo());
    }
}
3.2 后置处理器执行顺序

同一属性上如果同时加入依赖注入注解 @Autowired , @Resoureces 时注入类型的优先级.

System.out.println("CommonAnnotationBeanPostProcessor 优先级 => "+ (Ordered.LOWEST_PRECEDENCE -3) );
System.out.println("CommonAnnotationBeanPostProcessor 优先级 => "+ (Ordered.LOWEST_PRECEDENCE -2) );
4.ApplicationContext实现 4.1 ClassPathXmlApplicationContext
@Slf4j
public class TestApplicationContext {
    public static void main(String[] args) {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        log.info(" <<<<<<<<<<<<<<<<<<<<<<<< 读取之前");
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            log.info("beanDefinitionName => " + beanDefinitionName);
        }
        log.info(" <<<<<<<<<<<<<<<<<<<<<<<< 读取之后");
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        reader.loadBeanDefinitions(new ClassPathResource("bean01.xml"));
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            log.info("beanDefinitionName => " + beanDefinitionName);
        }
    }
}
4.2 FileSystemXmlApplicationContext

略

4.3 AnnotationConfigApplicationContext

较为经典的容器 , 基于java配置类来创建

@Slf4j
public class TestApplicationContext {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            System.err.println("beanDefinitionName => " + beanDefinitionName);
        }

        System.err.println("bean2.bean1 => " + context.getBean("beanTwo", BeanTwo.class).getBeanOne());
    }
}

BeanTwo.java

public class BeanTwo {
    private BeanOne beanOne;
    public void setBeanOne(BeanOne beanOne) {
        this.beanOne = beanOne;
    }

    public BeanOne getBeanOne() {
        return beanOne;
    }
}

BeanOne.java

public class BeanOne {}
4.4 AnnotationConfigServletWebServerApplicationContext

较为经典的容器 , 基于java配置类来创建 , 用于web环境

WebConfig

@Configuration
public class WebConfig {
    
    @Bean
    public ServletWebServerFactory servletWebServerFactory(){
        return new TomcatServletWebServerFactory();
    }

    
    @Bean
    public DispatcherServlet dispatcherServlet(){
        return new DispatcherServlet();
    }

    
    @Bean
    public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet){
        return new DispatcherServletRegistrationBean(dispatcherServlet,"/");
    }

    
    @Bean("/hello")
    public Controller controllerOne(){
        return (request, response) -> {
            response.getWriter().println("hello");
            return null;
        };
    }
}

serverStarter : 8080

public class TestAnnotationConfigConfigServletWebServerApplicationContext {
    public static void main(String[] args) {
        AnnotationConfigServletWebServerApplicationContext context =
                                            new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);

    }
}

请求 : localhost:8080/hello

5.Bean生命周期 5.1 bean生命周期

构造=>依赖注入=>Bean初始化=>Bean销毁

LifeCycleBean.java

@Component
@Slf4j
public class LifeCycleBean {

    
    public LifeCycleBean() { log.info("1 => 构造 LifeCycle()");}

    
    @Autowired
    public void autowire(@Value("${JAVA_HOME}") String javaHome){
        log.info("2 => 依赖注入 : {}",javaHome);
    }

    
    @PostConstruct
    public void init(){
        log.info("3 => Bean初始化");
    }

    
    @PreDestroy
    public void destroy(){
        log.info("4 => Bean销毁");
    }
}

SpringBootRun

@SpringBootApplication
public class Springdemo2Application {

    public static void main(String[] args) {

        ConfigurableApplicationContext context = SpringApplication.run(Springdemo2Application.class, args);
        
        context.close();
    }
}

5.2 Bean后处理器

提供bean生命周期各个阶段的扩展

@Slf4j
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor , DestructionAwareBeanPostProcessor {

    @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");
        }
        //如果返回不为 null 则替换原本的bean
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if(beanName.equals("lifeCycleBean")){
            log.info("<<<<<< 实例化之后执行 , 这里如果返回 false 会跳过依赖注入阶段");
            //return 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;
    }
}

6.设计模式-模板方法

提高代码的扩展能力

BeanPostProcessor.java

public interface BeanPostProcessor {
    void dependencyInject(Object bean); //希望对依赖注入阶段的阶段进行扩展
}

MyBeanFactory.java

@Slf4j
public class MyBeanFactory {

    private List processors = new ArrayList<>();

    // 模板方法  Template Method Pattern 提高现有代码扩展能力
    public Object getBean(){
        Object bean = new Object();
        log.info("构造 => {}" , bean);
        log.info("依赖注入 => {}" , bean); //@Autowired , @Resource
        
        for (BeanPostProcessor processor : processors) {
            processor.dependencyInject(bean);
        }
        log.info("初始化 => {}" , bean);
        return bean;
    }

    public void addBeanPostProcessor(BeanPostProcessor postProcessor){
        processors.add(postProcessor);
    }
}

TestMethodTemplate.java

@Slf4j
public class TestMethodTemplate {
    public static void main(String[] args) {
        MyBeanFactory beanFactory = new MyBeanFactory();
        beanFactory.addBeanPostProcessor(bean -> {
            log.info("加入解析@Autowired的能力");
        });
        beanFactory.addBeanPostProcessor(bean -> {
            log.info("加入解析@Resource的能力");
        });
        beanFactory.getBean();
    }
}

7.Bean后处理器

Bean1.java

@Slf4j
public class Bean1 {

    private Bean2 bean2;

    @Autowired
    public void setBean2(Bean2 bean2) {
        log.info("@Autowired 生效 : {} " , bean2);
        this.bean2 = bean2;
    }

    @Autowired
    private Bean3 bean3;

    @Resource
    public void setBean3(Bean3 bean3) {
        log.info("@Resource 生效 : {}" , bean3);
        this.bean3 = bean3;
    }

    private String home;

    @Autowired
    public void setHome(@Value("${JAVA_HOME}") String home) {
        log.info("@Value 生效 : {}" , home);
        this.home = home;
    }

    @PostConstruct
    public void init(){
        log.info("@PostConstruct 生效");
    }

    @PreDestroy
    public void destroy(){
        log.info("@PreDestroy生效");
    }

    @Override
    public String toString() {
        return "Bean1{" +
                "bean2=" + bean2 +
                ", bean3=" + bean3 +
                ", home='" + home + ''' +
                '}';
    }
}

Bean2.java

public class Bean2 {}

Bean3.java

public class Bean3 {}

Bean4.java

@Data
@ConfigurationProperties(prefix = "java")
public class Bean4 {
    private String home;
    private String version;
}

TestGenericAppContext.java

@Slf4j
public class TestGenericAppContext {
    public static void main(String[] args) {
        //GenericApplicationContext 是一个 干净的容器
        GenericApplicationContext context = new GenericApplicationContext();

        //用原始的方法注册三个Bean
        context.registerBean("bean1", Bean1.class);
        context.registerBean("bean2", Bean2.class);
        context.registerBean("bean3", Bean3.class);
        context.registerBean("bean4", Bean4.class);

        
        context.getDefaultListableBeanFactory().setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());//@Value
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class); // 解析 @Autowired 和 @Value  的后处理器
        context.registerBean(CommonAnnotationBeanPostProcessor.class); //解析 @Resource @PostConstruct @PreDestroy
        ConfigurationPropertiesBindingPostProcessor.register(context.getDefaultListableBeanFactory()); //@ConfigurationProperties



        //初始化容器
        context.refresh(); //执行beanFactory后处理器, 添加bean后处理器 , 初始化所有单例

        log.info("ConfigProper => {}",context.getBean(Bean4.class));

        //销毁容器
        context.close();

    }
}
7.1 运行流程-AutowiredAnnotationBeanPostProcessor

@Slf4j
public class DigInAutowired {
    public static void main(String[] args) throws Throwable {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2",new Bean2()); //不会执行Bean创建 , 依赖注入 , 初始化
        beanFactory.registerSingleton("bean3",new Bean3());
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); //@Value
        beanFactory.addEmbeddedValueResolver(strVal -> new StandardEnvironment().resolvePlaceholders(strVal));//${} el表达式的解析器

        //查找哪些属性 , 方法添加@Autowired , 这称之为 InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);

        Bean1 bean1 = new Bean1();
//        log.info("获取解析@Autowired & @Value 能力之前 => {}" , bean1);
//        processor.postProcessProperties(null,bean1,"bean1"); //执行依赖注入 解析@Autowired , @Value
//        log.info("获取解析@Autowired & @Value 能力之后 => {}" , bean1);

        
        Method findAutowiringMetadata =
                AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadata.setAccessible(true);
        InjectionMetadata metadata =
                (InjectionMetadata) findAutowiringMetadata.invoke(processor, "bean1", Bean1.class, null);//获取Bean1 上 加了 @Value @Autowired 的成员变量,方法参数信息
        log.info("metadata => {} ",metadata);

        //调用 InjectionMetadata 来进行注入 , 注入时按类型查找值
        metadata.inject(bean1,"bean1",null);
        log.info("bean1 => {}" ,bean1);
 }
7.2 InjectMetadata

Bean1.java

@Slf4j
public class Bean1 {

    private Bean2 bean2;

    @Autowired
    public void setBean2(Bean2 bean2) {
        log.info("@Autowired 生效 : {} " , bean2);
        this.bean2 = bean2;
    }

    @Autowired
    private Bean3 bean3;

    @Resource
    public void setBean3(Bean3 bean3) {
        log.info("@Resource 生效 : {}" , bean3);
        this.bean3 = bean3;
    }

    private String home;

    @Autowired
    public void setHome(@Value("${JAVA_HOME}") String home) {
        log.info("@Value 生效 : {}" , home);
        this.home = home;
    }

    @PostConstruct
    public void init(){
        log.info("@PostConstruct 生效");
    }

    @PreDestroy
    public void destroy(){
        log.info("@PreDestroy生效");
    }

    @Override
    public String toString() {
        return "Bean1{" +
                "bean2=" + bean2 +
                ", bean3=" + bean3 +
                ", home='" + home + ''' +
                '}';
    }
}

@Slf4j
public class DigInAutowired {
    public static void main(String[] args) throws Throwable {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2",new Bean2()); //不会执行Bean创建 , 依赖注入 , 初始化
        beanFactory.registerSingleton("bean3",new Bean3());
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); //@Value
        beanFactory.addEmbeddedValueResolver(strVal -> new StandardEnvironment().resolvePlaceholders(strVal));//${} el表达式的解析器

        //查找哪些属性 , 方法添加@Autowired , 这称之为 InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);

        Bean1 bean1 = new Bean1();
//        log.info("获取解析@Autowired & @Value 能力之前 => {}" , bean1);
//        processor.postProcessProperties(null,bean1,"bean1"); //执行依赖注入 解析@Autowired , @Value
//        log.info("获取解析@Autowired & @Value 能力之后 => {}" , bean1);

        
        Method findAutowiringMetadata =
                AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadata.setAccessible(true);
        InjectionMetadata metadata =
                (InjectionMetadata) findAutowiringMetadata.invoke(processor, "bean1", Bean1.class, null);//获取Bean1 上 加了 @Value @Autowired 的成员变量,方法参数信息
        log.info("metadata => {} ",metadata);

        //调用 InjectionMetadata 来进行注入 , 注入时按类型查找值
        metadata.inject(bean1,"bean1",null);
        
        log.info("bean1 => {}" ,bean1);



        //3.如果按类型查找值 , inject内部做的一些事情
        Field bean3 = Bean1.class.getDeclaredField("bean3");
        DependencyDescriptor dd1 = new DependencyDescriptor(bean3,false);
        Object bean31 = beanFactory.doResolveDependency(dd1, null, null, null);
        log.info(" <<<<<<<<< bean3 => {}" ,bean31);

        Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
        DependencyDescriptor dd2 = new DependencyDescriptor(new MethodParameter(setBean2,0),false);
        Object bean21 = beanFactory.doResolveDependency(dd2, null, null, null);
        log.info("<<<<<<<<< bean2 => {}" ,bean21);

        Method setHome = Bean1.class.getDeclaredMethod("setHome", String.class);
        DependencyDescriptor dd3 = new DependencyDescriptor(new MethodParameter(setHome,0),false);
        Object javaHome = beanFactory.doResolveDependency(dd3, null, null, null);
        log.info("<<<<<<<<< java_home => {}" ,javaHome.toString());

    }
}

8.常见工厂后处理器 8.1 @Component-ConfigurationClassPostProcessor

解析 @Component @Bean @Import @ImportResource 

SpringConfig.class

@Configuration
@Slf4j
@ComponentScan("com.nanoswarm.springpra.bean")
public class SpringConfig {

    @Bean
    public Bean1 bean1() {return new Bean1();}

    public void eat(){
        log.info("eat something");
    }

    @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.setPassword("root");
        dataSource.setUsername("root");
        dataSource.setUrl("jdbc:mysql://192.168.64.140/test");
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        return dataSource;
    }
}

Main.class

@Slf4j
public class TestDefaultListenableApp {
    public static void main(String[] args) {

        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("springConfig", SpringConfig.class);
        context.registerBean(ConfigurationClassPostProcessor.class); //解析 @ComponentScan  @Bean  @Import  @ImportResource
        context.registerBean(MapperScannerConfigurer.class,
                bd -> bd.getPropertyValues().add("basePackage","com.nanoswarm.springdemopra.bean")); //@MapperScanner
        context.refresh();

        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            log.info("beanDefinitionName => {}" , beanDefinitionName);
        }

        context.close();
    }
}
8.2 模拟-ConfigurationClassPostProcessor

Bean1.class

public class Bean1 {
}

Bean2.class

@Component
public class Bean2 {
}

 Bean3.class

@Component
public class Bean3 {
}

Bean4.class

@Controller
public class Bean4 {
}

Config.class

@Configuration
@ComponentScan("com.nanoswarm.springdemopra.bean")
public class SpringConfig {
    @Bean
    public Bean1 bean1(){return new Bean1();}
}

Main.java

@Slf4j
public class TestDefaultListenableApp {
    public static void main(String[] args) throws IOException {

        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("springConfig", SpringConfig.class);
//        context.registerBean(ConfigurationClassPostProcessor.class); //解析 @Component  @Bean  @Import  @ImportResource
//        context.registerBean(MapperScannerConfigurer.class,
//                bd -> bd.getPropertyValues().add("basePackage","com.nanoswarm.springdemopra.bean")); //@MapperScanner


        ComponentScan componentScan = AnnotationUtils.findAnnotation(SpringConfig.class, ComponentScan.class); //扫描这个类上的@ComponentScan注解
        if(componentScan != null){
            for (String path : componentScan.basePackages()) {
                log.info("path => {}",path);
                //com.nanoswarm.springdemopra.bean -> classpath*:/com/nanoswarm/springdemopra/bean*.class
                //将包名转换为路径
                String resourcePath = "classpath*:" + path.replace(".","/") + "*.class";
                log.info("resourcePath => {}" , resourcePath);
                CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();//解析类中的各种元素
                Resource[] resources = context.getResources(resourcePath);
                for (Resource resource : resources) {
                   //log.info("   resource => {}",resource);
                    MetadataReader reader = factory.getMetadataReader(resource);
                    log.info("类名 => {}" , reader.getClassMetadata().getClassName()); //解析类名
                    log.info("是否加了 @Component 注解 => {}",reader.getAnnotationMetadata().hasAnnotation(Component.class.getName())); //是否有指定注解
                    log.info("是否加了 @Component 派生注解 => {}" ,reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName())); //是否有指定派生注解

                }
            }
        }


        context.refresh();

        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            log.info("beanDefinitionName => {}" , beanDefinitionName);
        }

        context.close();
    }
}
8.3 自定义CompentScanPostProcessor

Main.java

@Slf4j										//BeanDefinitionRegistryPostProcessor
public class ComponentScanPostProcessor implements BeanFactoryPostProcessor {

    
    @SneakyThrows
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        ComponentScan componentScan = AnnotationUtils.findAnnotation(SpringConfig.class, ComponentScan.class); //扫描这个类上的@ComponentScan注解
        if(componentScan != null){
            for (String path : componentScan.basePackages()) {
                log.info("path => {}",path);
                //com.nanoswarm.springdemopra.bean -> classpath*:/com/nanoswarm/springdemopra/bean*.class
                String resourcePath = "classpath:" + path.replace(".","/") + "*.class";
                log.info("resourcePath => {}" , resourcePath);
                CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();//解析类中的各种元素		
                //根据路径通配符找到资源
                Resource[] resources = new PathMatchingResourcePatternResolver().getResources(resourcePath);
                AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator(); //BeanName生成器
                for (Resource resource : resources) {
                    //log.info("   resource => {}",resource);
                    MetadataReader reader = factory.getMetadataReader(resource);
                    AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
//                    log.info("类名 => {}" , reader.getClassMetadata().getClassName()); //解析类名
//                    log.info("是否加了 @Component 注解 => {}",reader.getAnnotationMetadata().hasAnnotation(Component.class.getName())); //是否有指定注解
//                    log.info("是否加了 @Component 派生注解 => {}" ,reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName())); //是否有指定派生注解

                    //如果加了注解 , 变成bean定义 , 加入bean工厂
                    if(annotationMetadata.hasAnnotation(Component.class.getName()) || annotationMetadata.hasMetaAnnotation(Component.class.getName())){
                        AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(reader.getClassMetadata().getClassName()).getBeanDefinition();

                        if(configurableListableBeanFactory instanceof DefaultListableBeanFactory){
                          DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)configurableListableBeanFactory;
                            String beanName = generator.generateBeanName(bd, beanFactory);
                            //加入到bean工厂
                            beanFactory.registerBeanDefinition(beanName,bd);
                        }
                    }
                }
            }
        }
    }
}

Main.class

@Slf4j
public class TestDefaultListenableApp {
    public static void main(String[] args) {

        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("springConfig", SpringConfig.class);
        context.registerBean(ComponentScanPostProcessor.class); //解析 @ComponentScan  @Bean  @Import  @ImportResource


        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            log.info("beanDefinitionName => {}" , beanDefinitionName);
        }

        context.close();
    }
}
8.4 工厂后处理器模拟-@Bean

simulateBeanFactory.java

@Slf4j
public class AtBeanPostProcessor implements BeanFactoryPostProcessor {
    @SneakyThrows
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
        MetadataReader reader = factory.getMetadataReader(new ClassPathResource("com/nanoswarm/springpra/config/SpringConfig.class"));
        Set methods = reader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
        for (MethodMetadata method : methods) {
            log.info("method => {}" ,method.getMethodName());

            String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString(); //获取@Bean注解上的属性值(initMethod)

            //创建BeanDefinition
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
            builder.setFactoryMethodOnBean(method.getMethodName(),"springConfig");

            builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);//工厂方法参数
            if(initMethod.length() > 0){
                builder.setInitMethodName(initMethod);
            }
            AbstractBeanDefinition bd = builder.getBeanDefinition();

            if(configurableListableBeanFactory instanceof DefaultListableBeanFactory){
               DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)configurableListableBeanFactory;
               beanFactory.registerBeanDefinition(method.getMethodName(),bd);
            }
        }
    }
}

Main.java

@Slf4j
public class TestBeanPostProcessor {
    public static void main(String[] args) throws IOException {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("springConfig", SpringConfig.class);

        context.registerBean(AtBeanPostProcessor.class);

        context.refresh();

        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            log.info("beanDefinitionName => {}" ,beanDefinitionName);
        }

        context.close();
    }
}

Bean1 => null

Bean2 => @Component

Bean3 => @Component

Bean4 => @Controller

8.5 工厂后处理器模拟-@Mapper

8.5.1 方式一 : 在配置类中逐个添加

SpringConfig.java

   @Bean
    public MapperFactoryBean mapper1(SqlSessionFactory sqlSessionFactory){
        MapperFactoryBean factory = new MapperFactoryBean<>(Mapper1.class);
        factory.setSqlSessionFactory(sqlSessionFactory);
        return factory;
    }

8.5.2 扫描mapper

MapperPostProcessor.java

public class MapperPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @SneakyThrows
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {

        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources("classpath:com/nanoswarm/springpra/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 db = BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class)
                        .addConstructorArgValue(classMetadata.getClassName())
                        .setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)
                        .getBeanDefinition();
                AbstractBeanDefinition db2 = BeanDefinitionBuilder.genericBeanDefinition(classMetadata.getClassName()).getBeanDefinition();
                String name = generator.generateBeanName(db2, beanFactory);
                beanFactory.registerBeanDefinition(name,db);
            }
        }

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}

Main.java

@Slf4j
public class TestBeanPostProcessor {
    public static void main(String[] args) throws IOException {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("springConfig", SpringConfig.class);

        context.registerBean(AtBeanPostProcessor.class);
        context.registerBean(MapperPostProcessor.class);

        context.refresh();

        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            log.info("beanDefinitionName => {}" ,beanDefinitionName);
        }

        context.close();
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/950550.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号