一、@Enable 注解
Spring Framework
- @EnableWebMvc Web MVC
- @EnableTransactionManangement 事务管理
- @EnableCaching 缓存
- @EnableMBeanExport JMX
- @EnableAsync 异步处理
- @EnableWebFlux Web Flux
- @EnableAspectJAutoProxy AspectJ代理
Spring Boot
- @EnableAutoConfiguration 自动装配
- @EnableManageMentContext Actuator管理模块
- @EnableConfigurationProperties 配置属性绑定
- @EnableOAuth2Sso OAuth2
Spring Cloud
- @EnableEurekaServer Eureka服务器模块
- @EnableConfigServer 配置服务器模块
- @EnableFeignClients Feign
- @EnableZuulProxy 服务网关Zuul
- @EnableCircuitBreaker 服务熔断
二、自定义@Enable注解
自定义@Enable注解有两种方式:
- 基于@Import + @Configuration 注解实现
- 基于ImportSelector 或者 ImportBeanDefinitionRegistrar接口实现;
基于@Import实现示例:
@EnableWebMvc
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
// configuration
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
}
基于接ImportSelector实现
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({CachingConfigurationSelector.class})
public @interface EnableCaching {
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default 2147483647;
}
// AdviceModeImportSelector
public class CachingConfigurationSelector extends AdviceModeImportSelector<EnableCaching> {
}
// ImportSelector
public abstract class AdviceModeImportSelector<A extends Annotation> implements ImportSelector {
}
自己动手、丰衣足食
(1) @Import + @Configuration
@Configuration
public class HelloWorldConfiguration {
@Bean
public String helloWorld(){
return "Hello, World";
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(HelloWorldConfiguration.class)
public @interface EnabaleHelloWorld {
}
@EnabaleHelloWorld
@Configuration
public class HelloWorldApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(HelloWorldApplication.class);
context.refresh();
String helloWorld = context.getBean("helloWorld", String.class);
System.out.println(helloWorld);
context.close();
}
}
(2) @Import +ImportSelector
// 1. server & server type
public interface Server {
/**
* 启动服务
*/
void start();
/**
* 关闭服务
*/
void stop();
}
// 2.http & ftp
public enum ServerType {
HTTP,FTP
}
public class HttpServer implements Server {
@Override
public void start() {
System.out.println("Http Server starting");
}
@Override
public void stop() {
System.out.println("Http Server stoping");
}
}
public class FtpServer implements Server {
@Override
public void start() {
System.out.println("Ftp Server starting");
}
@Override
public void stop() {
System.out.println("Ftp Server stoping");
}
}
// 3.ImportSelector
public class ServerImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 获取注解的属性列表:支持派生及递归
Map<String, Object> annotationAttributes = annotationMetadata.getAnnotationAttributes(EnableServer.class.getName());
// 获取服务器类型
ServerType type = (ServerType) annotationAttributes.get("type");
switch (type) {
case FTP:
return new String[]{FtpServer.class.getName()};
case HTTP:
return new String[]{HttpServer.class.getName()};
}
return new String[0];
}
}
// 4. @Enable
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ServerImportSelector.class)
public @interface EnableServer {
/**
* 设置服务器类型
*
* @return
*/
ServerType type();
}
// test
@Configuration
@EnableServer(type = ServerType.FTP)
public class EnableServerApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(EnableServerApplication.class);
context.refresh();
Server server = context.getBean(Server.class);
server.start();
server.stop();
}
}
(3) @Import + ImportBeanDefinitionRegistrar
// 1.ImportBeanDefinitionRegistrar
public class ServerImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
ImportSelector selector = new ServerImportSelector();
String[] selectedClassNames = selector.selectImports(importingClassMetadata);
// 创建Bean定义
Stream.of(selectedClassNames)
// BeanDefinition构造器
.map(BeanDefinitionBuilder::genericBeanDefinition)
// BeanDefinition
.map(BeanDefinitionBuilder::getBeanDefinition)
.forEach(abstractBeanDefinition -> {
BeanDefinitionReaderUtils.registerWithGeneratedName(abstractBeanDefinition, registry);
});
}
}
// 2.与ImportSelector对比,替换Import导入类即可
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//@Import(ServerImportSelector.class)
@Import(ServerImportBeanDefinitionRegistrar.class)
public @interface EnableServer {
/**
* 设置服务器类型
*
* @return
*/
ServerType type();
}