• SpringBoot框架(4) 类装配及Bean装配监听器


    1、普通方式装配类对象  

    (1)添加带有@Bean注解的方法 
    User.java(带@Component注解)
    1 package com.demo.boot.bootenable.beanDemo1;
    2 
    3 import org.springframework.stereotype.Component;
    4 
    5 @Component
    6 public class User {
    7 }
    User.java

     
    (2)需要装配的类添加@Component注解

    Book.java(不带@Component注解)
    1 package com.demo.boot.bootenable.beanDemo1;
    2 
    3 public class Book {
    4 }
    Book.java

    ==》打印

     1 package com.demo.boot.bootenable.beanDemo1;
     2 
     3 import org.springframework.boot.SpringApplication;
     4 import org.springframework.boot.autoconfigure.SpringBootApplication;
     5 import org.springframework.context.ConfigurableApplicationContext;
     6 import org.springframework.context.annotation.Bean;
     7 
     8 /**
     9  * 普通方式装配类对象
    10  * (1)添加带有@Bean注解的方法
    11  * (2)需要装配的类添加@Component注解
    12  */
    13 @SpringBootApplication
    14 public class BootEnableApplication {
    15 
    16     @Bean
    17     public  Book createBook(){
    18         return new Book();
    19     }
    20 
    21     public static void main(String[] args) {
    22         ConfigurableApplicationContext context = SpringApplication.run(com.demo.boot.bootenable.beanDemo1.BootEnableApplication.class);
    23         User user = context.getBean(User.class);
    24         System.out.println(user);
    25 
    26         Book book = context.getBean(Book.class);
    27         System.out.println(book);
    28         context.close();
    29     }
    30 }
    main方法

    com.demo.boot.bootenable.beanDemo1.User@3301500b
    com.demo.boot.bootenable.beanDemo1.Book@24b52d3e

    2、使用@Import方式装配类对象

    准备两个测试类User.java和Book.java

    1 package com.demo.boot.bootenable.beanDemo2;
    2 
    3 public class User {
    4 }
    User.java
    1 package com.demo.boot.bootenable.beanDemo2;
    2 
    3 public class Book {
    4 }
    Book.java

    (1)方式1==》@Import({User.class,Book.class}) //直接添加需要装配的类

            ==》代码结构

            

     1 package com.demo.boot.bootenable.beanDemo2;
     2 
     3 import org.springframework.boot.SpringApplication;
     4 import org.springframework.boot.autoconfigure.SpringBootApplication;
     5 import org.springframework.context.ConfigurableApplicationContext;
     6 import org.springframework.context.annotation.Import;
     7 
     8 /**
     9  * 使用@Import方式装配类对象
    10  */
    11 @SpringBootApplication
    12 @Import({User.class,Book.class})//方式1==》直接添加需要装配的类
    13 public class BootEnableApplication {
    14     public static void main(String[] args) {
    15         ConfigurableApplicationContext context2 = SpringApplication.run(BootEnableApplication.class);
    16         User user = context2.getBean(User.class);
    17         System.out.println(user);
    18 
    19         Book book = context2.getBean(Book.class);
    20         System.out.println(book);
    21         context2.close();
    22     }
    23 }
    Application.java

            ==》输出

    com.demo.boot.bootenable.beanDemo2.User@24855019
    com.demo.boot.bootenable.beanDemo2.Book@3abd581e

    (2)方式2==》@Import(BeanImportSelector.class) //BeanImportSelector重写ImportSelector类的selectImport方法

            ==》代码结构

             

     1 package com.demo.boot.bootenable.beanDemo2;
     2 
     3 import org.springframework.context.annotation.ImportSelector;
     4 import org.springframework.core.type.AnnotationMetadata;
     5 
     6 public class BeanImportSelector implements ImportSelector {
     7     @Override
     8     public String[] selectImports(AnnotationMetadata annotationMetadata) {
     9         return new String[]{
    10                 "com.demo.boot.bootenable.beanDemo2.Book",
    11                 "com.demo.boot.bootenable.beanDemo2.User"
    12         };
    13     }
    14 }
    BeanImportSelector.java
     1 package com.demo.boot.bootenable.beanDemo2;
     2 
     3 import org.springframework.boot.SpringApplication;
     4 import org.springframework.boot.autoconfigure.SpringBootApplication;
     5 import org.springframework.context.ConfigurableApplicationContext;
     6 import org.springframework.context.annotation.Import;
     7 
     8 /**
     9  * 使用@Import方式装配类对象
    10  */
    11 @SpringBootApplication
    12 //@Import({User.class,Book.class})//方式1==》直接添加需要装配的类
    13 @Import(BeanImportSelector.class)//方式2==》BeanImportSelector重写ImportSelector类的selectImport方法
    14 public class BootEnableApplication {
    15     public static void main(String[] args) {
    16         ConfigurableApplicationContext context2 = SpringApplication.run(BootEnableApplication.class);
    17         User user = context2.getBean(User.class);
    18         System.out.println(user);
    19 
    20         Book book = context2.getBean(Book.class);
    21         System.out.println(book);
    22         context2.close();
    23     }
    24 }
    Application.java

            ==》输出

    com.demo.boot.bootenable.beanDemo2.User@88d6f9b
    com.demo.boot.bootenable.beanDemo2.Book@47d93e0d

    (3)方式3==》@Import(MyBeanDefinitionRegistrar.class) //MyBeanDefinitionRegistrar重写ImportBeanDefinitionRegistrar类的registerBeanDefinitions方法

             ==》代码结构

             

     1 package com.demo.boot.bootenable.beanDemo3;
     2 
     3 import org.springframework.beans.factory.config.BeanDefinition;
     4 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
     5 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
     6 import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
     7 import org.springframework.core.type.AnnotationMetadata;
     8 
     9 /**
    10  * ImportBeanDefinitionRegistrar可以为装配对象添加额外的属性
    11  */
    12 public class MyBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    13     @Override
    14     public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
    15         BeanDefinitionBuilder userBDB = BeanDefinitionBuilder.rootBeanDefinition(User.class);
    16         BeanDefinition userBD = userBDB.getBeanDefinition();
    17         beanDefinitionRegistry.registerBeanDefinition("user",userBD);
    18 
    19         BeanDefinitionBuilder bookBDB = BeanDefinitionBuilder.rootBeanDefinition(Book.class);
    20         BeanDefinition bookBD = bookBDB.getBeanDefinition();
    21         beanDefinitionRegistry.registerBeanDefinition("book",bookBD);
    22     }
    23 }
    MyBeanDefinitionRegistrar.java
     1 package com.demo.boot.bootenable.beanDemo3;
     2 
     3 import org.springframework.boot.SpringApplication;
     4 import org.springframework.boot.autoconfigure.SpringBootApplication;
     5 import org.springframework.context.ConfigurableApplicationContext;
     6 import org.springframework.context.annotation.Import;
     7 
     8 /**
     9  * 使用@Import方式装配类对象
    10  */
    11 @SpringBootApplication
    12 //@Import({User.class,Book.class})//方式1==》直接添加需要装配的类
    13 //@Import(BeanImportSelector.class)//方式2==》BeanImportSelector重写ImportSelector类的selectImport方法
    14 @Import(MyBeanDefinitionRegistrar.class)//方式3==》MyBeanDefinitionRegistrar重写ImportBeanDefinitionRegistrar类的registerBeanDefinitions方法
    15 public class BootEnableApplication {
    16     public static void main(String[] args) {
    17         ConfigurableApplicationContext context3 = SpringApplication.run(BootEnableApplication.class);
    18         User user = context3.getBean("user", User.class);
    19         System.out.println(user);
    20 
    21         Book book = context3.getBean("book", Book.class);
    22         System.out.println(book);
    23         context3.close();
    24     }
    25 }
    Application.java

            ==》输出

    com.demo.boot.bootenable.beanDemo3.User@4d0402b
    com.demo.boot.bootenable.beanDemo3.Book@2fa7ae9

    备注:以上demo中,都是指定需要装配的类,不指定则不会自动自动装配

    3、Bean装配监听器

      bean在装配过程中会执行一系列方法,其中有postProcessBeforeInitialization --> afterPropertiesSet --> init-method -- > postProcessAfterInitialization。

      (1)postProcessBeforeInitialization方法,在bean初始化之前执行

      (2)afterPropertiesSet方法,初始化bean的时候执行

      (3)nit-method方法,初始化bean的时候执行

      (4)postProcessAfterInitialization方法,在bean初始化之后执行。

      因此,我们可以在装配时,进行拦截处理。这里demo选用重写postProcessBeforeInitialization方法

        代码结构

        

    3.1 创建类 MyBeanDefinitionProcessor继承BeanPostProcessor,添加属性packages的构造器,并重写postProcessBeforeInitialization方法,实现类装配前打印。

     1 package com.demo.boot.bootenable.smple;
     2 
     3 import org.springframework.beans.BeansException;
     4 import org.springframework.beans.factory.config.BeanPostProcessor;
     5 
     6 import java.util.ArrayList;
     7 
     8 public class MyBeanDefinitionProcessor implements BeanPostProcessor {
     9 
    10     private ArrayList<String> packages;
    11 
    12     public ArrayList<String> getPackages() {
    13         return packages;
    14     }
    15 
    16     public void setPackages(ArrayList<String> packages) {
    17         this.packages = packages;
    18     }
    19 
    20     @Override
    21     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    22 
    23         for (String pack : packages) {
    24             if (bean.getClass().getName().startsWith(pack)) {
    25                 System.out.println("instance name:" + bean.getClass().getName());
    26             }
    27         }
    28         return bean;
    29     }
    30 }
    MyBeanDefinitionProcessor

    3.2 创建类ScannerPackegeRegistar implements ImportBeanDefinitionRegistrar,重写registerBeanDefinitions方法,把自定义的MyBeanDefinitionProcessor注册进去。

     1 package com.demo.boot.bootenable.smple;
     2 
     3 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
     4 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
     5 import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
     6 import org.springframework.core.type.AnnotationMetadata;
     7 import org.springframework.stereotype.Component;
     8 
     9 import java.util.Arrays;
    10 import java.util.List;
    11 
    12 @Component
    13 public class ScannerPackegeRegistar implements ImportBeanDefinitionRegistrar {
    14     /**
    15      * 注册实体对象被装配前回调方法
    16      * @param annotationMetadata
    17      * @param beanDefinitionRegistry
    18      */
    19     @Override
    20     public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
    21         String[] strArr = (String[]) annotationMetadata
    22                 .getAnnotationAttributes(EnableScanner.class.getName())
    23                 .get("packages");
    24 
    25         List<String> packages = Arrays.asList(strArr);
    26         System.out.println(packages);
    27         BeanDefinitionBuilder dbd = BeanDefinitionBuilder.rootBeanDefinition(MyBeanDefinitionProcessor.class);
    28         dbd.addPropertyValue("packages", packages);
    29 
    30         beanDefinitionRegistry.registerBeanDefinition(MyBeanDefinitionProcessor.class.getName(), dbd.getBeanDefinition());
    31     }
    32 
    33 }
    ScannerPackegeRegistar.java

    3.3 自定义注解EnableScanner

     1 package com.demo.boot.bootenable.smple;
     2 
     3 import org.springframework.context.annotation.Import;
     4 import java.lang.annotation.*;
     5 
     6 @Target({ElementType.TYPE})
     7 @Retention(RetentionPolicy.RUNTIME)
     8 @Documented
     9 @Import(ScannerPackegeRegistar.class)
    10 public @interface EnableScanner {
    11     String[] packages();
    12 }
    EnableScanner.java

    3.4 创建Person.java、Student.java和UserVO.java类

    1 package com.demo.boot.bootenable.smple.bean;
    2 
    3 import org.springframework.stereotype.Component;
    4 
    5 @Component
    6 public class Person {
    7 }
    Person.java
    1 package com.demo.boot.bootenable.smple.bean;
    2 
    3 import org.springframework.stereotype.Component;
    4 
    5 @Component
    6 public class Student {
    7 }
    Student.java
    1 package com.demo.boot.bootenable.smple.vo;
    2 
    3 import org.springframework.stereotype.Component;
    4 
    5 @Component
    6 public class UserVO {
    7 }
    UserVO.java

    3.5 Application

     1 package com.demo.boot.bootenable.smple;
     2 
     3 import org.springframework.boot.SpringApplication;
     4 import org.springframework.boot.autoconfigure.SpringBootApplication;
     5 import org.springframework.context.ConfigurableApplicationContext;
     6 
     7 @SpringBootApplication
     8 @EnableScanner(packages = {"com.demo.boot.bootenable.smple.bean", "com.demo.boot.bootenable.smple.vo"})//启用监控扫描类的注解
     9 public class ScannerPackegeApplication {
    10     public static void main(String[] args) {
    11         ConfigurableApplicationContext context = SpringApplication.run(ScannerPackegeApplication.class, args);
    12 
    13         context.close();
    14     }
    15 }
    Application.java

    输出结果

    instance name:com.demo.boot.bootenable.smple.bean.Person
    instance name:com.demo.boot.bootenable.smple.bean.Student
    instance name:com.demo.boot.bootenable.smple.vo.UserVO

    总结思路

    1、把类装配到SpringBoot容器管理主要分两大类

        (1)普通方式:直接在类上加@Component注解,或者在创建对象方法加上@Bean注解

        (2)通过@Import注解:直接指定需要装配的类,传入

                                                 重写ImportSelector类的selectImport方法的类,

                                                 或重写ImportBeanDefinitionRegistrar类的registerBeanDefinitions方法

    2、Bean装配监听器

      (1)定义注解,接受需要装配类的包名

      (2)创建ImportBeanDefinitionRegistrar的子类ScannerPackegeRegistar,重写registerBeanDefinitions方法,作用是把监听器注册到SpringBoot初始化Bean的过程中。

      (3)创建BeanPostProcessor的子类MyBeanDefinitionProcessor,重写postProcessBeforeInitialization方法,作用是监听在bean初始化前装配的类。

    如果该文章对你有所帮助,请点个赞支持下,谢谢!
  • 相关阅读:
    DAY09(for语句)
    Python 下载 tushare 数据,然后调用 C++ DLL 计算 wMA 存入本地 csv 文件再 python 读取
    Python socket编程之八:阶段性总结
    Ctex + Lyx = 自用 Latex 编辑环境
    matlab下二重积分的蒙特卡洛算法
    实验9 根据材料编程
    实验5 编写、调试具有多个段的程序
    实验4 [bx]和loop的使用
    实验3 编程、编译、连接、跟踪
    汇编语言第三章总结
  • 原文地址:https://www.cnblogs.com/lfhappy/p/10939015.html
Copyright © 2020-2023  润新知