这两天写使用 netty + springboot
的方式实现代理服务器,在此须希望通过 auto configuration
的方式配置。
- 定制
XXXProperties
属性
@Data
public class XXXProperties {
private String key;
private String value;
private int weight;
}
- 构建
XXXBean
工厂
public class XXXFactoryBean implements FactoryBean<XXXBean>, ApplicationContextAware {
/**
* 应用服务器上下文
*/
private ApplicationContext applicationContext;
@Getter
@Setter
private XXXProperties xxxProperties;
@Override
public XXXBean getObject() throws Exception {
return new XXXBean();
}
@Override
public Class<?> getObjectType() {
return XXXBean.class;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
- 注册
XXXBean
到Spring
框架
@Component
public class XXXBeanDefinitionRegister implements BeanDefinitionRegistryPostProcessor, EnvironmentAware {
// 绑定 xxx 前缀开始的属性
private static final String XXX_PREFIX = "xxx";
private Environment environment;
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
Binder binder = Binder.get(environment);
// 没配置xxx, 忽略
BindResult<XXXProperties> bindResult = binder.bind(XXX_PREFIX, XXXProperties.class);
if (!bindResult.isBound()) {
return;
}
XXXProperties xxxProperties = bindResult.get();
if (StringUtils.isEmpty(xxxProperties.getName())) {
return;
}
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(ProxyServerFactoryBean.class)
// 添加属性参数
.addPropertyValue("xxxProperties", xxxProperties)
// 生成 XXXBean 实例
.getBeanDefinition();
registry.registerBeanDefinition(xxxProperties.getName(), beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
}
- 定义
XXXBeanAutoConfiguration
自动导入类
@Configuration
@EnableConfigurationProperties({XXXProperties.class})
public class XXXBeanAutoConfiguration implements ResourceLoaderAware {
/**
* 资源加载器
*/
private ResourceLoader resourceLoader;
/**
* XXX 代理配置
*/
private final XXXProperties xxxProperties;
public XXXBeanAutoConfiguration(XXXProperties xxxProperties) {
this.xxxProperties = xxxProperties;
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
}
- 若需要在创建过程中需要有数据校验,则需实现
BeanPostProcessor
来实现,比如:
@Component
public class BoundPortCheckerPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof XXXBean) {
XXXBean server = (XXXBean) bean;
// 校验数据,如果不符合规则,则直接抛出 BeansException 即可
}
return bean;
}
}
- 在
application.yaml
文件中定义即可
xxx:
yyy: AAAA
- 添加依赖
// 添加 Annotation Processor 模块 (自定义 properties 实例)
compileOnly "org.springframework.boot:spring-boot-configuration-processor"
- 自动启动某些服务
在 spring
体系下,当 Spring
容器加载所有 bean
并完成初始化之后,会接着回调实现 SmartLifecycle
接口的类中对应的方法(start()
方法)。因此,通常情况下,比如 netty
等都可以 SmartLifecycle
接口的方式来进行启动后台 netty
服务。