首先写一个我们自己的HelloWorld配置类
1、基于"注解驱动"实现@Enable模块
@Configuration
public class HelloWorldConfiguration {
@Bean
public String helloWorld() {
return "Hello,World";
}
}
再模仿Spring Cloud Feign源码解析 中的@EnableFeignClients代码写一个我们自己的标签
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(HelloWorldConfiguration.class)
public @interface EnableHelloWorld {
}
@EnableFeignClients Import的是FeignClientsRegistrar.class,而我们这里导入的是HelloWorldConfiguration.class
再编写一个引导类来看一下效果。
@EnableHelloWorld
@Configuration
public class EnabledHelloWorldBootstrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(EnabledHelloWorldBootstrap.class);
context.refresh();
String helloWorld = context.getBean("helloWorld", String.class);
System.out.printf("helloWorld = %s \n",helloWorld);
context.close();
}
}
运行结果(部分)
15:00:46.060 main DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
15:00:46.065 main DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
15:00:46.069 main DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'helloWorld'
helloWorld = Hello,World
15:00:46.069 main INFO org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@31a5c39e: startup date Thu Nov 21 15:00:45 CST 2019; root of context hierarchy
15:00:46.070 main DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
15:00:46.070 main DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5427c60c: defining beans org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,enabledHelloWorldBootstrap,com.cloud.demo.config.HelloWorldConfiguration,helloWorld; root of factory hierarchy
2、基于"接口编程"实现@Enable模块
基于ImportSelector接口实现
假设当前应用支持两种服务类型:HTTP和FTP,通过@EnableServer设置服务器类型(type)提供对应的服务
先定义一个服务接口
public interface Server {
/**
* 启动服务器
*/
void start();
/**
* 关闭服务器
*/
void stop();
/**
* 服务器类型
*/
enum Type {
HTTP, //HTTP服务器
FTP //FTP服务器
}
}
两个实现类
@Component
public class HTTPServer implements Server {
@Override
public void start() {
System.out.println("HTTP服务器启动中...");
}
@Override
public void stop() {
System.out.println("HTTP服务器关闭中...");
}
}
@Component
public class FTPServer implements Server {
@Override
public void start() {
System.out.println("FTP服务器启动中...");
}
@Override
public void stop() {
System.out.println("FTP服务器关闭中...");
}
}
实现@Enable模块驱动
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ServerImportSelector.class)
public @interface EnableServer {
/**
* 设置服务器类型
* @return
*/
Server.Type type();
}
实现Server ImportSelector接口
public class ServerImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//读取EnableServer中所有的属性方法,本例中仅有type()属性方法
//其中key为属性方法的名称,value为属性方法的返回对象
Map<String,Object> annotationAttributes = importingClassMetadata
.getAnnotationAttributes(EnableServer.class.getName());
//获取名为type的属性方法,并且强制转换成Server.Type类型
Server.Type type = (Server.Type) annotationAttributes.get("type");
//导入的类名称数组
String[] importClassNames = new String[0];
switch (type) {
case HTTP:
importClassNames = new String[]{HTTPServer.class.getName()};
break;
case FTP:
importClassNames = new String[]{FTPServer.class.getName()};
break;
}
return importClassNames;
}
}
标注@EnableServer到引导类EnableServerBootstrap
@Configuration
@EnableServer(type = Server.Type.HTTP)
public class EnableServerBootstrap {
public static void main(String[] args) {
//构建Annotation配置驱动Spring上下文
AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext();
//注册当前引导类(被@Configuration标注)到Spring上下文
context.register(EnableServerBootstrap.class);
//启动上下文
context.refresh();
//获取Server Bean对象,实际为HttpServer
Server server = context.getBean(Server.class);
//启动服务器
server.start();
//关闭服务器
server.stop();
}
}
运行结果(部分)
16:52:08.966 main DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default org.springframework.context.support.DefaultLifecycleProcessor@2fb3536e
16:52:08.967 main DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
16:52:08.975 main DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
16:52:08.979 main DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'com.cloud.demo.server.HTTPServer'
HTTP服务器启动中...
HTTP服务器关闭中...
基于ImportBeanDefinitionRegistrar接口实现
替换上例中的ServerImportSelector即可
public class ServerImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//复用 {@link ServerImportSelector} 实现,避免重复劳动
ImportSelector importSelector = new ServerImportSelector();
//筛选Class名称集合
String[] selectedClassNames = importSelector.selectImports(importingClassMetadata);
//创建Bean定义
Stream.of(selectedClassNames)
//转化为BeanDefinitionBuilder对象
.map(BeanDefinitionBuilder::genericBeanDefinition)
//转化为BeanDefinition
.map(BeanDefinitionBuilder::getBeanDefinition)
//注册BeanDefinition到BeanDefinitionRegistry
.forEach(beanDefinition -> BeanDefinitionReaderUtils
.registerWithGeneratedName(beanDefinition,registry));
}
}
替换@EnableServer的@Import
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ServerImportBeanDefinitionRegistrar.class)
public @interface EnableServer {
/**
* 设置服务器类型
* @return
*/
Server.Type type();
}
运行结果
17:38:53.147 main DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
17:38:53.150 main DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
17:38:53.152 main DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'com.cloud.demo.server.HTTPServer#0'
HTTP服务器启动中...
HTTP服务器关闭中...