Special Car Introduction
This is a special bus going to the Spring Boot Transaction Ideas. In the last article, we detailed the principles of Spring Boot Transaction implementation in the Spring Boot Transaction Source Analysis Train [1], which is based on the previous one.
Before the battle, let's review the main points of the last article:
- Postprocessor: Intercept and process beans
- Faces: consisting of points of tangency and notifications
- Tangent: Used to match matching classes and methods
- Notification: for proxy processing
Special Car Problem
- How do I intercept and process beans with a back-end processor?
- How do I define the facets?
- How do I define a tangent point?
- How do I define notifications?
- How to achieve automatic configuration?
Special Car Analysis
The implementation is based on Spring Boot and requires the following dependencies to be added
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
Define in turn according to the questions mentioned above
Define a bean postprocessor, with special attention to not having to redefine if transaction attributes are used in your project
/** * Be sure to declare Infrastructure AdvisorAutoProxyCreator for post-processing of bean s * * @return */ @Bean public InfrastructureAdvisorAutoProxyCreator infrastructureAdvisorAutoProxyCreator() { return new InfrastructureAdvisorAutoProxyCreator(); }
Define Faces
public class BeanFactorySystemLogAdvisor extends AbstractBeanFactoryPointcutAdvisor { /** * Define the point of tangency */ private final SystemLogPointcut point = new SystemLogPointcut(); @Override public Pointcut getPointcut() { return this.point; } }
Define the point of tangency
public class SystemLogPointcut extends StaticMethodMatcherPointcut { @Override public boolean matches(Method method, Class<?> targetClass) { // Find @SystemLog annotation property on class AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes( targetClass, SystemLog.class, false, false); if (Objects.nonNull(attributes)) { return true; } // The @SystemLog annotation property on the lookup method attributes = AnnotatedElementUtils.findMergedAnnotationAttributes( method, SystemLog.class, false, false); return Objects.nonNull(attributes); } }
Define Notifications
@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 { /** * Define Faces * Be sure to specify the @Role comment here * * @return */ @Role(BeanDefinition.ROLE_INFRASTRUCTURE) @Bean public BeanFactorySystemLogAdvisor beanFactorySystemLogAdvisor() { BeanFactorySystemLogAdvisor advisor = new BeanFactorySystemLogAdvisor(); advisor.setAdvice(systemLogInterceptor()); return advisor; } /** * Define Notifications * * @return */ @Bean public SystemLogInterceptor systemLogInterceptor() { return new SystemLogInterceptor(); } /** * Be sure to declare Infrastructure AdvisorAutoProxyCreator for post-processing of bean s * * @return */ @Bean public InfrastructureAdvisorAutoProxyCreator infrastructureAdvisorAutoProxyCreator() { return new InfrastructureAdvisorAutoProxyCreator(); } }
Definition Notes
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SystemLog { }
Special Vehicle Integration Business
Define Controller
@RestController public class SystemLogController { @Autowired private SystemLogService systemLogService; @GetMapping("/log") public String hello(@RequestParam("name") String name) throws InterruptedException { return systemLogService.log(name); } }
Define business methods
@Slf4j @Service public class SystemLogService { @SystemLog public String log(String name) throws InterruptedException { log.info("Execute business methods"); TimeUnit.SECONDS.sleep(1); return "hello " + name; } }
Define Startup Class
@SpringBootApplication public class TransactionImitateApplication { public static void main(String[] args) { SpringApplication.run(TransactionImitateApplication.class, args); } }
Visit 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]=========================================[execute method:argument:advisor]=====================2019-08-23 11 11:13:36.038 INFO 23227 --- [nio-8080-8080-exec-13:13:36.030 INFO 2311 11 11 11:13:36.030 INFO 2322227 --- [nio-8080-13:13:13:13:36.030 exec.boot.example.service.SystemLogService LogService:execute business method 2019-0880-23 11:13:37.038 INFO 23227 --- [nio-8080-eXec-1] c.b.example.config.SystemLogInterceptor: ======[method execute time:1004]======
You can see that log slicing is accomplished by simulating the implementation of the @Transaction annotation.
Special Vehicle Summary
- First we need to define a Bean Post Processor to intercept processing beans
- Then define the facet, and define the point of tangency in the facet
- Logic to implement a cut-in in a point of tangency, such as here our implementation logic is to find out if a class or method has the @SystemLog annotation
- Define notifications to complete agent work
- Auto-assemble, declare our facets, notifications, Bean post-processor in the configuration class
- Integrated Business
Special Vehicle Review
Looking back at the first five questions:
- How do I intercept and process beans with a back-end processor?Declare the postprocessor directly in the configuration class
- How do I define the facets?Inherit AbstractBeanFactoryPointcutAdvisor and declare it in the configuration class
- How do I define a tangent point?Inherit StaticMethodMatcherPointcut to implement matches method
- How do I define notifications?Implement MethodInterceptor interface and invoke method
- How to achieve automatic configuration?Customize the configuration class to declare all Bean s that need to be added to the container
Last
Teacher, [Advanced Java architect], wins 15W+ programmer's attention on all platforms in just one year, focusing on sharing 20 advanced architecture topics such as Java Advanced, Architecture Technology, High Concurrency, Micro Services, BAT Interview, redis, JVM Tuning, Springboot Source Code, mysql Tuning, etc. and focusing on [Advanced Java architect] replying to [Architecture] for a complete set of 2019 architect videos.
Reload instructions: Be sure to indicate the source (this article was first published under Public Number: [Advanced java architect]