【参考】https://blog.csdn.net/Janson_Lin/article/details/87778878
https://blog.csdn.net/qq_36872046/article/details/83662761
https://www.cnblogs.com/hermanlife/p/10019473.html
一般用来声明配置类,可以使用 @Component注解替代,不过使用Configuration注解声明配置类更加语义化。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
@AliasFor(
annotation = Component.class
)
String value() default "";
boolean proxyBeanMethods() default true;
}
用法:1.导入配置类, 2.导入普通类(4.2之前只支持导入配置类)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* {@link Configuration @Configuration}, {@link ImportSelector},
* {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
*/
Class<?>[] value();
}
示例1:@Configuration注解类
@Configuration
public class MoonBookConfiguration {
@Bean
public BookService bookService() {
return new BookServiceImpl();
}
}
@Configuration
// 可以同时导入多个配置类,比如:@Import({A.class,B.class})
@Import(MoonBookConfiguration.class)
public class MoonUserConfiguration {
@Bean
public UserService userService(BookService bookService) {
return new UserServiceImpl(bookService);
}
}
示例2:普通类
public class BookServiceImpl implements BookService {
public BookServiceImpl() {
System.out.println("实例化BookService.");
}
}
@Configuration
// 可以同时导入多个配置类,比如:@Import({A.class,B.class}
@Import(BookServiceImpl.class)
public class MoonUserConfiguration {
public MoonUserConfiguration() {
System.out.println("实例化MoonUserConfiguration");
}
@Bean
public UserService userService(BookService bookService) {
return new UserServiceImpl(bookService);
}
}
Springboot对注解的处理都发生在AbstractApplicationContext -> refresh() -> invokeBeanFactoryPostProcessors(beanFactory) -> ConfigurationClassPostProcessor -> postProcessBeanDefinitionRegistry()方法中。
在 ConfigurationClassParser -> processConfigurationClass() -> doProcessConfigurationClass() 方法中我们找到了@Component, @PropertySource, @ComponentScan, @Import, @ImportResource的处理.
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
import处理流程:
@EnableAutoConfiguration注解表示开启Spring Boot自动配置功能,Spring Boot会根据应用的依赖、自定义的bean、classpath下有没有某个类 等等因素来猜测你需要的bean,然后注册到IOC容器中。
那 @EnableAutoConfiguration是如何推算出你的需求?看@Import(EnableAutoConfigurationImportSelector.class).
@Import注解用于导入类,并将这个类作为一个bean的定义注册到容器中,这里它将把 EnableAutoConfigurationImportSelector作为bean注入到容器中,而这个类会扫描所有的jar包,将所有符合条件的@EnableAutoConfiguration配置都加载到容器中:
// 来自 org.springframework.boot.autoconfigure下的META-INF/spring.factories
// 配置的key = EnableAutoConfiguration,与代码中一致
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration\
.....
开启了这个注解,也就意味这springboot 帮你集成了大批的热门,火热的开源技术,不再需要你导入集成配置.
另外一个作用,就是如果有自定义的类,并不是在当前启动类的扫描路径下,也可以通过这种方式被扫进来被容器管理.
比如:
package com.one.bean.auto.configuration;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyEnableAutoConfiguration {
public MyEnableAutoConfiguration() {
System.out.println("实例化MyEnableAutoConfiguration.");
}
}
package com.one.bean.spring.boot.autoconfiguration;
import com.one.bean.auto.configuration.MyEnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* 用来测试@AutoEnableConfiguration,
* 看导入的包是不是要在本类能扫描到的路径下
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class);
MyEnableAutoConfiguration bean = context.getBean(MyEnableAutoConfiguration.class);
context.close();
}
}
并在spring.factories里配置:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.one.bean.auto.configuration.MyEnableAutoConfiguration