若是這是你第二次看到師長的文章,說明你在覬覦個人美色!java
點贊+關注再看,養成習慣mysql
沒別的意思,就是須要你的窺屏^_^
程序員
該趟專車是開往基於Spring Boot事務思想實戰的專車,在上一篇 搭上SpringBoot事務源碼分析專車[1]中咱們詳細介紹了Spring Boot事務實現的原理,這一篇是基於上一篇的實戰。web
在實戰以前,咱們再次回顧下上篇文章講解的重點:面試
實現是以Spring Boot爲基礎,須要添加以下依賴redis
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
按照如上提到的問題依次定義spring
定義bean後置處理器,特別注意,若是項目中使用到了事務特性,就不須要重複定義sql
/** * 必定要聲明InfrastructureAdvisorAutoProxyCreator,用於實現bean的後置處理 * * @return */ @Bean public InfrastructureAdvisorAutoProxyCreator infrastructureAdvisorAutoProxyCreator() { return new InfrastructureAdvisorAutoProxyCreator(); }
定義切面mysql優化
public class BeanFactorySystemLogAdvisor extends AbstractBeanFactoryPointcutAdvisor { /** * 定義切點 */ private final SystemLogPointcut point = new SystemLogPointcut(); @Override public Pointcut getPointcut() { return this.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); } }
定義通知
@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; } }
自動配置
@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(); } }
定義註解
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SystemLog { }
定義控制器
@RestController public class SystemLogController { @Autowired private SystemLogService systemLogService; @GetMapping("/log") public String hello(@RequestParam("name") String name) throws InterruptedException { return systemLogService.log(name); } }
定義業務方法
@Slf4j @Service public class SystemLogService { @SystemLog public String log(String name) throws InterruptedException { log.info("執行業務方法"); TimeUnit.SECONDS.sleep(1); return "hello " + name; } }
定義啓動類
@SpringBootApplication public class TransactionImitateApplication { public static void main(String[] args) { SpringApplication.run(TransactionImitateApplication.class, args); } }
訪問http://localhost:8080/log?name=advisor
查看控制檯
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]======
能夠看到經過模擬@Transaction註解的實現方式,完成了日誌切面功能。
回顧下開頭的五個問題:
師長,【java進階架構師】號主,短短一年在各大平臺斬獲15W+程序員關注,專一分享Java進階、架構技術、高併發、微服務、BAT面試、redis專題、JVM調優、Springboot源碼、mysql優化等20大進階架構專題,關注【java進階架構師】回覆【架構】領取2019架構師完整視頻一套。轉載說明:請務必註明來源(本文首發於公衆號:【java進階架構師】)