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初始化前装配的类。

posted @ 2019-05-29 00:33  天晴修屋顶  阅读(1376)  评论(0编辑  收藏  举报