Foreword
If this is your second time to see the teacher to show that you covet my beauty!
+ Thumbs attention again, a habit
No other meaning, is the need for a glimpse of your screen ^ _ ^
Car introduced
The car trip is a car bound for Spring Boot based on actual transactions thoughts on a catch SpringBoot car transaction source code analysis [1], we detail the principles of Spring Boot affairs to achieve, this one is based on one of actual combat.
Before combat, we look back on the focus of the next article to explain again:
- Postprocessor: to intercept and handle Bean
- Section: a cut-off point and the composition of notification
- Tangent point: matching method for matching the class and
- Notice: a proxy processing
Car problem
- How to use post processor for Bean to intercept and process?
- How to define the cut?
- How to define the cut-off point?
- How to define notification?
- How to achieve automatic configuration?
Car analysis
Spring Boot realization is based on the need to add the following dependence
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
Are sequentially defined in terms of the problem mentioned above,
Defined postprocessor bean, note that if used in the project characteristics of the transaction, there is no need to repeat the definition
/**
* 一定要声明InfrastructureAdvisorAutoProxyCreator,用于实现bean的后置处理
*
* @return
*/
@Bean
public InfrastructureAdvisorAutoProxyCreator infrastructureAdvisorAutoProxyCreator() {
return new InfrastructureAdvisorAutoProxyCreator();
}
The definition section
public class BeanFactorySystemLogAdvisor extends AbstractBeanFactoryPointcutAdvisor {
/**
* 定义切点
*/
private final SystemLogPointcut point = new SystemLogPointcut();
@Override
public Pointcut getPointcut() {
return this.point;
}
}
Defined cut point
public class SystemLogPointcut extends StaticMethodMatcherPointcut {
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 查找类上@SystemLog注解属性
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
targetClass, SystemLog.class, false, false);
if (Objects.nonNull(attributes)) {
return true;
}
// 查找方法上@SystemLog注解属性
attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
method, SystemLog.class, false, false);
return Objects.nonNull(attributes);
}
}
Custom notification
@Slf4j
public class SystemLogInterceptor implements MethodInterceptor, Serializable {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
String className = method.getDeclaringClass().getSimpleName();
String methodName = method.getName();
log.info("======[" + className + "#" + methodName + " method begin execute]======");
Arrays.stream(invocation.getArguments()).forEach(argument -> log.info("======[execute method argument:" + argument + "]======"));
Long time1 = Clock.systemDefaultZone().millis();
Object result = invocation.proceed();
Long time2 = Clock.systemDefaultZone().millis();
log.info("======[method execute time:" + (time2 - time1) + "]======");
return result;
}
}
Automatic Configuration
@Configuration
public class ProxySystemLogConfiguration {
/**
* 定义切面
* 此处一定要指定@Role注解
*
* @return
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Bean
public BeanFactorySystemLogAdvisor beanFactorySystemLogAdvisor() {
BeanFactorySystemLogAdvisor advisor = new BeanFactorySystemLogAdvisor();
advisor.setAdvice(systemLogInterceptor());
return advisor;
}
/**
* 定义通知
*
* @return
*/
@Bean
public SystemLogInterceptor systemLogInterceptor() {
return new SystemLogInterceptor();
}
/**
* 一定要声明InfrastructureAdvisorAutoProxyCreator,用于实现bean的后置处理
*
* @return
*/
@Bean
public InfrastructureAdvisorAutoProxyCreator infrastructureAdvisorAutoProxyCreator() {
return new InfrastructureAdvisorAutoProxyCreator();
}
}
Defined Note
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemLog {
}
Car integration business
Define the Director
@RestController
public class SystemLogController {
@Autowired
private SystemLogService systemLogService;
@GetMapping("/log")
public String hello(@RequestParam("name") String name) throws InterruptedException {
return systemLogService.log(name);
}
}
Definition of business methods
@Slf4j
@Service
public class SystemLogService {
@SystemLog
public String log(String name) throws InterruptedException {
log.info("执行业务方法");
TimeUnit.SECONDS.sleep(1);
return "hello " + name;
}
}
Define start classes
@SpringBootApplication
public class TransactionImitateApplication {
public static void main(String[] args) {
SpringApplication.run(TransactionImitateApplication.class, args);
}
}
访问http://localhost:8080/log?name=advisor
View Console
2019-08-23 11:13:36.029 INFO 23227 --- [nio-8080-exec-1] c.b.example.config.SystemLogInterceptor : ======[SystemLogService#log method begin execute]======2019-08-23 11:13:36.030 INFO 23227 --- [nio-8080-exec-1] c.b.example.config.SystemLogInterceptor : ======[execute method argument:advisor]======2019-08-23 11:13:36.038 INFO 23227 --- [nio-8080-exec-1] c.boot.example.service.SystemLogService : 执行业务方法2019-08-23 11:13:37.038 INFO 23227 --- [nio-8080-exec-1] c.b.example.config.SystemLogInterceptor : ======[method execute time:1004]======
Annotations can be seen by simulating @Transaction implementation, completed the logging function section.
Car summary
- First we need to define a post-processor Bean, Bean used to intercept processing
- Then the definition section, the section is defined tangent point
- Cut point cut implemented in logic, such as logic here is that we realize if they contain @SystemLog find notes on classes or methods
- Custom notifications, complete agency work
- Automatic assembly, our section, notification, Bean post processor declared in the configuration class
- Integrated Services
Car review
Recalling the beginning of the next five questions:
- How to use post processor for Bean to intercept and process? Declared directly in the post-processor configuration class
- How to define the cut? Inherit AbstractBeanFactoryPointcutAdvisor, and it declared in the configuration class
- 如何定义切点?继承StaticMethodMatcherPointcut,实现matches方法
- 如何定义通知?实现MethodInterceptor接口,实现invoke方法
- 如何实现自动配置?自定义配置类,声明所有需要加入容器的Bean
最后
师长,【java进阶架构师】号主,短短一年在各大平台斩获15W+程序员关注,专注分享Java进阶、架构技术、高并发、微服务、BAT面试、redis专题、JVM调优、Springboot源码、mysql优化等20大进阶架构专题,关注【java进阶架构师】回复【架构】领取2019架构师完整视频一套。
转载说明:请务必注明来源(本文首发于公众号:【java进阶架构师】)