zoukankan      html  css  js  c++  java
  • springBoot @Enable*注解的工作原理

    使用注解实现异步

    RunnableDemo

    package com.boot.enable.bootenable;
    
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.stereotype.Component;
    
    import java.util.concurrent.TimeUnit;
    
    @Component
    public class RunnableDemo implements Runnable {
    
        @Async // 异步方式执行方法
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println("----------------"+ (i +1));
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    测试类

    package com.boot.enable.bootenable;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.scheduling.annotation.EnableAsync;
    
    @SpringBootApplication
    @EnableAsync
    public class BootEnableApplication {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context =
                    SpringApplication.run(BootEnableApplication.class, args);
            Runnable bean = context.getBean(Runnable.class);
            System.out.println("-----------start-----------");
            bean.run();
            System.out.println("-----------end-----------");
    
            context.close();
        }
    }

    运行结果分析:

    run方法打印的内容是异步进行的,是独立于主线程外的线程,所以-----------end-----------打印后,run方法依然再进行打印

    几种装配方式

    1.普通的方式

    package com.boot.enable.imp.demo;
    
    public class Book {
    }
    package com.boot.enable.imp.demo;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class User {
    }
    package com.boot.enable.imp.demo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.annotation.Bean;
    
    /**
     * 普通方式装配
     */
    @SpringBootApplication
    public class ImportApplication {
    
        @Bean
        public Book book() {
            return new Book();
        }
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context =
                    SpringApplication.run(ImportApplication.class, args);
            System.out.println(context.getBean(User.class));
            System.out.println(context.getBean(Book.class));
    
            context.close();
        }
    }

    使用@Import装配的第一种方式

    package com.boot.enable.imp.demo1;
    
    public class Book {
    }
    package com.boot.enable.imp.demo1;
    
    public class User {
    }
    package com.boot.enable.imp.demo1;
    
    import org.springframework.context.annotation.ImportSelector;
    import org.springframework.core.type.AnnotationMetadata;
    
    public class BeanImportSelector implements ImportSelector {//不需要注入其他属性时使用
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            return new String[]{"com.boot.enable.imp.demo1.Book"
                    ,"com.boot.enable.imp.demo1.User"};
        }
    }
    package com.boot.enable.imp.demo1;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.annotation.Import;
    
    /**
     * 使用@Import方式装配
     */
    @SpringBootApplication
    // @Import({User.class, Book.class})
    @Import(BeanImportSelector.class)
    public class ImportApplication1 {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context =
                    SpringApplication.run(ImportApplication1.class, args);
            System.out.println(context.getBean(User.class));
            System.out.println(context.getBean(Book.class));
    
            context.close();
        }
    }

    使用@Import装配 第二种方式

    package com.boot.enable.imp.demo2;
    
    import org.springframework.beans.factory.config.BeanDefinition;
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
    import org.springframework.core.type.AnnotationMetadata;
    
    public class MyBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {//有属性注入时使用
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            // 创建构建器对象
            BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(User.class);
            BeanDefinition beanDefinition = bdb.getBeanDefinition();
            registry.registerBeanDefinition("user", beanDefinition);
    
            BeanDefinitionBuilder bdb1 = BeanDefinitionBuilder.rootBeanDefinition(Book.class);
            BeanDefinition beanDefinition1 = bdb1.getBeanDefinition();
            registry.registerBeanDefinition("book", beanDefinition1);
        }
    }
    package com.boot.enable.imp.demo2;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.annotation.Import;
    
    /**
     * 使用@Import方式装配
     */
    @SpringBootApplication
    @Import(MyBeanDefinitionRegistrar.class)
    public class ImportApplication1 {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context =
                    SpringApplication.run(ImportApplication1.class, args);
            System.out.println(context.getBean("user",User.class));
            System.out.println(context.getBean(Book.class));
    
            context.close();
        }
    }

    实例演示:注解注册监控器实现

    实体类准备:

    package com.boot.enable.sample.bean;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class Person {
    }
    public class Person1 {
    }
    package com.boot.enable.sample.bean;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class Person2 {
    }
    package com.boot.enable.sample.vo;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class UserVO {
    }

    自定义一个注解(借用@Import机制)

    package com.boot.enable.sample;
    
    import org.springframework.context.annotation.Import;
    
    import java.lang.annotation.*;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(ScannerPackageRegistrar.class)
    public @interface EnableScanner {
        String[] packages();
    }
    package com.boot.enable.sample;
    
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
    import org.springframework.core.type.AnnotationMetadata;
    
    import java.util.Arrays;
    import java.util.List;
    
    public class ScannerPackageRegistrar implements ImportBeanDefinitionRegistrar {
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
                                            BeanDefinitionRegistry registry) {
            String[] attrs = (String[]) importingClassMetadata
                    .getAnnotationAttributes(EnableScanner.class.getName())
                    .get("packages");//获取到注解的packages属性
            List<String> packages = Arrays.asList(attrs);
            System.out.println(packages);
            BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(MyBeanDefinitionProcessor.class);
            bdb.addPropertyValue("packages", packages);//注入属性
    
            registry.registerBeanDefinition(MyBeanDefinitionProcessor.class.getName(), bdb.getBeanDefinition());//装配到Spring容器中
    
        }
    }
    package com.boot.enable.sample;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    
    import java.util.List;
    
    public class MyBeanDefinitionProcessor implements BeanPostProcessor {
    
        private List<String> packages;
    
        public List<String> getPackages() {
            return packages;
        }
    
        public void setPackages(List<String> packages) {
            this.packages = packages;
        }
    
        @Override//扫描出装配到容器中的类并打印出对应实例
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            for (String pack : packages) {
    
                if (bean.getClass().getName().startsWith(pack)) {
                    System.out.println("instance bean:"+bean.getClass().getName());
                }
            }
            return bean;
        }
    }

    测试类

    package com.boot.enable.sample;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    
    /**
     * 普通方式装配
     */
    @SpringBootApplication
    @EnableScanner(packages ={"com.boot.enable.sample.bean","com.boot.enable.sample.vo"}) // 启用监控扫描类的注解
    public class ScannerPackageApplication {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context =
                    SpringApplication.run(ScannerPackageApplication.class, args);
            context.close();
    
            new ScannerPackageApplication().callFunction(new FunctionImpl());//回调演示
        }
    
    
        interface Function {
            void hello();
        }
    
        static class FunctionImpl implements Function {
    
            @Override
            public void hello() {
                System.out.println("调用了FunctionImpl->Hello方法");
            }
        }
    
        public void callFunction(Function fun) {
         //处理其他事  fun.hello(); //回调
         //处理其他事 } }

    打印结果(打印出注入到Spring容器中的实例,Person1未加注解,所以未打印)

     监控器流程图解

  • 相关阅读:
    5个排序算法
    原生侧边栏sidebar
    静态方法、实例方法、继承
    函数作用域之闭包与this!
    OOP面向对象编程(下)
    数组方法篇二
    对象
    nginx windows负载均衡入门
    NVelocity
    python3简单爬虫
  • 原文地址:https://www.cnblogs.com/lm970585581/p/9807609.html
Copyright © 2011-2022 走看看