Spring Boot(九) @Enable*注解的工作原理

1. @EnableConfigurationProperties

    0.是用来启用一个特性,这个特性就是,可以把配置文件的属性注入到bean里面去,一般是要和@ConfigurationProperties一起使用
    1.Demo
        1.在启动类里加上 @EnableConfigurationProperties 注解(@SpringBootConfiguration 里有这个注解)
@EnableConfigurationProperties
@ComponentScan
public class App {
    public static void main(String[] args) {
        ConfigurableApplicationContext context=SpringApplication.run(App.class, args);
        System.out.println(context.getBean(TomcatProperties.class));
        context.close();
    }
}
        2.创建一个TomcatProperties.java
@Component
@ConfigurationProperties("tomcat")
public class TomcatProperties {
    private String host;
    private int port;
    //get,set方法
}

2. 在SpringBoot中使用异步---- @EnableAsync、@Async

    0. @EnableAsync 起步启动,一般是和@Async一起使用
        1.Demo
            1.启动类
@EnableAsync
@ComponentScan
public class App {
    public static void main(String[] args) {
        ConfigurableApplicationContext context=SpringApplication.run(App.class, args);
        context.getBean(Runnable.class).run();
        System.out.println("-------------end------------");
        context.close();
    }
}
            2.Jeep.java
@Component
public class Jeep implements Runnable{
    @Async
    public void run() {
        try {
            for (int i = 0; i <3; i++) {
                System.out.println("-------------"+i);
                TimeUnit.SECONDS.sleep(1);
            }
        } catch (Exception e) {
            e.printStackTrace();
           }
    }
}


3. @Import

0.用来导入一个或多个类(会被Spring容器托管),或者是配置类(配置类里面的bean都会被Spring容器托管)
    1.一个bean
        @Import(User.class)
    2.多个bean(可以是数组)
        @Import({User.class,Role.class})
    3.bean的配置文件
        0.创建一个bean的配置文件 MyConfiguration.java
public class MyConfiguration {
    @Bean
    public Runnable getRunnable(){
        return ()->{};
    }
    @Bean
    public Runnable getRunnable2(){
        return ()->{};
    }
}
        1.应用
@Import(MyConfiguration.class)
				public class App2 {
					    public static void main(String[] args) {
        ConfigurableApplicationContext context=SpringApplication.run(App2.class, args);
        context.close();
    }
}
1.ImportSelector 接口----(一、将想要托管的bean动态地放入spring容器)
    0.使用这种方法,通过在 @Import中 输入不同的类,可以动态地返回一些需要使用的类(放入Spring容器托管起来),
      selectImports方法的返回值,必须是一个class(全称),该class会被Spring托管起来
    1.Demo
        1. 创建 MyImportSelector.java ,实现 ImportSelector
public class MyImportSelector implements ImportSelector {
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{User.class.getName(),Role.class.getName(),MyConfiguration.class.getName()};
    } 
}

        2.应用

@Import(MyConfiguration.class)
public class App2 {
    public static void main(String[] args) {
        ConfigurableApplicationContext context=SpringApplication.run(App2.class, args);
        context.close();
    }
}

2.ImportSelector 接口----(二、获取注解里的属性,可以动态地注册bean到spring容器里)
    1.Demo

       1.创建 EnableLog.java 注解 ,使用4个注解 

         @Target(ElementType.TYPE),@Retention(RetentionPolicy.RUNTIME), @Documented,@Import 

            0. @Import 里放入ImportSelector接口 的实现类
            1.代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MyImportSelector.class)
public @interface EnableLog {
    String name();
}
            2.获取 ImportSelector接口 的实现类 里的属性 (使用importingClassMetadata 参数里的 getAllAnnotationAttributes方法)
public class MyImportSelector implements ImportSelector {
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        System.out.println(importingClassMetadata.getAllAnnotationAttributes(EnableLog.class.getName()));
        /*
        * 这里可以获得注解的详细信息,然后根据信息动态的返回需要被spring容器管理的bean
        */
        return new String[]{User.class.getName(),Role.class.getName(),MyConfiguration.class.getName()};
    } 
}
            3.应用
@EnableLog(name = "spring boot")
public class App2 {
    public static void main(String[] args) {
        ConfigurableApplicationContext context=SpringApplication.run(App2.class, args);
        context.close();
    }
}

3.ImportSelector 接口----(三、可以 用 ImportBeanDefintionRegistrar 接口 来替换ImportSelector) 

    0. registerBeanDefinitions方法参数中有一个BeanDefinitionRegistry,它可以用来往spring容器里注入bean如此,我们就可以在 registerBeanDefinition方法里动态地注入bean
    1.Demo
        1.创建 MyImportBeanDefinitionRegistrar.java 实现 ImportBeanDefinitionRegistrar ,来注册bean
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        BeanDefinitionBuilder bdb=BeanDefinitionBuilder.rootBeanDefinition(User.class);
        registry.registerBeanDefinition("user", bdb.getBeanDefinition());
    }
}

        2.其他的和 ImportSelector一样Spring Boot @Enable*注解的工作原理

4.ImportBeanDefintionRegistrar 的例子

0.实现:将指定的包里的类打印出来

1.创建 EchoBeanPostProcessor.java

public class EchoBeanPostProcessor implements BeanPostProcessor {
	private List<String> packages;
	//get、set方法
	
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		for (String pack : packages) {
			if(bean.getClass().getName().startsWith(pack)){
				System.out.println("Echo bean:"+bean.getClass().getName());
			}
		}
		return bean;
	}
}	 

2.创建 EchoImportBeanDefinitionRegistrar 实现 ImportBeanDefinitionRegistrar

public class EchoImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		//获得 EnableEcho 注解的属性信息
		Map<String,Object> attr=importingClassMetadata.getAnnotationAttributes(EnableEcho.class.getName());
		String[] packArr=(String[])attr.get("packages");
		List<String> packages=Arrays.asList(packArr);
		System.out.println("packages:"+packages);
		//将 EchoBeanPostProcessor 注册到Spring容器
		BeanDefinitionBuilder bdb=BeanDefinitionBuilder.rootBeanDefinition(EchoBeanPostProcessor.class);
		bdb.addPropertyValue("packages", packages);
		registry.registerBeanDefinition(EchoBeanPostProcessor.class.getName(),bdb.getBeanDefinition() );
	}
}	

3.创建 EnableEcho.java

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EchoImportBeanDefinitionRegistrar.class)
public @interface EnableEcho {
	String[] packages();
}	

4.创建bean ,并注入到spring容器里

1.com.edu.spring.springboot.SpringBoot09.bean.Cat

@Component
public class Cat {
	
}			

2.com.edu.spring.springboot.SpringBoot09.vo.Dog

@Component
public class Dog {

}

5.应用

@EnableEcho(packages = { "com.edu.spring.springboot.SpringBoot09.vo" ,"com.edu.spring.springboot.SpringBoot09.bean"})
public class App2 {
	public static void main(String[] args) {
		ConfigurableApplicationContext context=SpringApplication.run(App2.class, args);
		context.close();
	}
}


猜你喜欢

转载自blog.csdn.net/lzj470612639/article/details/81049583