日志框架系列讲解文章
日志框架 - 基于spring-boot - 使用入门
日志框架 - 基于spring-boot - 设计
日志框架 - 基于spring-boot - 实现1 - 配置文件
日志框架 - 基于spring-boot - 实现2 - 消息定义及消息日志打印
日志框架 - 基于spring-boot - 实现3 - 关键字与三种消息解析器
日志框架 - 基于spring-boot - 实现4 - HTTP请求拦截
日志框架 - 基于spring-boot - 实现5 - 线程切换
日志框架 - 基于spring-boot - 实现6 - 自动装配
上一篇我们讲了框架实现的第五部分:如何在线程切换时保留上下文信息。
本篇主要讲框架实现的第六部分:自动装配
自动装配(AutoConfiguration)是 Spring Boot 框架提供的核心功能。本篇中我们主要使用自动装配实现将之前第一部分到第五部分实现的功能组装到一起。实现对业务代码编程人员无感知。具体实现如下。
/**
* 日志组件自动装配
*/
@Configuration
@ConditionalOnProperty(
value = "xpay.framework.logging.enabled",
havingValue = "true",
matchIfMissing = true)
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class LoggingAutoConfiguration {
@Value("${xpay.framework.executor.max-pool-size:16}")
int maxPoolSize;
/**
* 自定义线程池
* <p>
* 用于线程切换时的MDC延续
*/
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(maxPoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setTaskDecorator(new MDCTaskDecorator());
executor.setThreadNamePrefix("MDCAdaptTaskExcutor-");
executor.initialize();
return executor;
}
@Bean
public MessageToLogAspect messageToLogAspect() {
return new MessageToLogAspect();
}
@Bean
public DefaultKeywords defaultKeywords() {
return new DefaultKeywords();
}
@Bean
public MDCSpringMvcHandlerInterceptor mdcSpringMvcHandlerInterceptor() {
return new MDCSpringMvcHandlerInterceptor();
}
/**
* Filter与Interceptor装配
*/
@Configuration
protected static class LoggingWebConfiguration extends
WebMvcConfigurerAdapter {
@Autowired
MDCSpringMvcHandlerInterceptor mdcSpringMvcHandlerInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(mdcSpringMvcHandlerInterceptor);
}
}
/**
* Keywords装配
*/
@Configuration
@ConditionalOnExpression(
"'${xpay.framework.logging.keywords}' matches '^([^,]+,)+.*$'")
protected static class MessageResolveAutoConfiguration {
@Value("${xpay.framework.logging.keywords}")
String keywordsPropertyString;
@Bean
public List<Keyword> keywordList() {
String[] keywordsProStringSplits =
keywordsPropertyString.split(",");
return Stream.of(keywordsProStringSplits)
.map(Keyword::new)
.collect(Collectors.toList());
}
@Bean
@Order(3)
public JsonMessageResolver jsonMessageResolver(
List<Keyword> keywordList) {
return new JsonMessageResolver(keywordList);
}
@Bean
@Order(2)
public XmlMessageResolver xmlMessageResolver(
List<Keyword> keywordList) {
return new XmlMessageResolver(keywordList);
}
@Bean
@Order(1)
public KeyValueMessageResolver keyValueMessageResolver(
List<Keyword> keywordList) {
return new KeyValueMessageResolver(keywordList);
}
@Bean
@Scope(scopeName = SCOPE_PROTOTYPE,
proxyMode = ScopedProxyMode.TARGET_CLASS)
public MessageResolverChain messageResolverChain(
List<MessageResolver> resolvers) {
return new MessageResolverChainImpl(resolvers);
}
@Bean
public RequestReplaceServletFilter requestReplaceServletFilter() {
return new RequestReplaceServletFilter();
}
@Bean
public FilterRegistrationBean requestReplaceFilter
(RequestReplaceServletFilter requestReplaceFilter) {
FilterRegistrationBean filterRegistrationBean = new
FilterRegistrationBean(requestReplaceFilter);
filterRegistrationBean.setDispatcherTypes(ASYNC, REQUEST);
// filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE + 5);
return filterRegistrationBean;
}
}
}
至此,日志框架所有实现都已介绍了。有想法的小伙伴也可以在此基础上进行改进。实现想要的功能。