序文
これはあなたの場合は二回あなたは私の美しさを切望することを示すために、教師をご覧いただけます!
+再び親指の注意、習慣
他の意味は、^ _ ^画面の片鱗が必要ではありません
カー導入
車の旅が上の実際の取引の考えに基づいて春ブーツ行きの車でキャッチSpringBoot車のトランザクションソースコード解析 [1]、我々は詳細春ブート事務の原則を達成するために、この1は、のいずれかに基づいています実際の戦闘。
戦闘前に、我々は再び説明する次の記事の焦点を振り返ります:
- ポストプロセッサ:インターセプトとハンドルビーンへ
- セクション:カットオフポイントと通知の組成
- タンジェントポイント:クラスを一致させるためのマッチング方法と
- 注意:プロキシ処理
車の問題
- インターセプトとプロセスにBeanのポストプロセッサを使用する方法?
- カットを定義するには?
- カットオフポイントを定義するには?
- 通知を定義するには?
- 自動構成を実現するには?
車の分析
春ブーツの実現は、以下の依存関係を追加する必要性に基づいています
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
順次、上記の問題の観点から定義されています、
トランザクションのプロジェクトの特性に使用される場合には、定義を繰り返す必要がないことを定義したポストプロセッサ豆、ノート
/**
* 一定要声明InfrastructureAdvisorAutoProxyCreator,用于实现bean的后置处理
*
* @return
*/
@Bean
public InfrastructureAdvisorAutoProxyCreator infrastructureAdvisorAutoProxyCreator() {
return new InfrastructureAdvisorAutoProxyCreator();
}
定義セクション
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 /ログ名=顧問?
ビューコンソール
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実装を、シミュレートすることで見ることができます。
車の概要
- まず、我々はポストプロセッサビーンを定義する必要があり、Beanがインターセプト処理に使用しました
- 次に、定義セクション、セクションが定義されている接点
- なロジックなどのロジックで実装カットポイントカット、ここでは、彼らが@SystemLogがクラスやメソッドの上にノートを見つける含まれている場合は、私たちが気付いていることです
- カスタム通知、完全な派遣労働
- 自動組立、私たちのセクション、通知、ビーンポストプロセッサは、コンフィギュレーションクラスで宣言しました
- 統合サービス
車のレビュー
次の5つの質問の始まりを想起:
- インターセプトとプロセスにBeanのポストプロセッサを使用する方法?ポストプロセッサ構成クラスで直接宣言
- カットを定義するには?継承AbstractBeanFactoryPointcutAdvisor、それはコンフィギュレーションクラスで宣言しました
- 如何定义切点?继承StaticMethodMatcherPointcut,实现matches方法
- 如何定义通知?实现MethodInterceptor接口,实现invoke方法
- 如何实现自动配置?自定义配置类,声明所有需要加入容器的Bean
最后
师长,【java进阶架构师】号主,短短一年在各大平台斩获15W+程序员关注,专注分享Java进阶、架构技术、高并发、微服务、BAT面试、redis专题、JVM调优、Springboot源码、mysql优化等20大进阶架构专题,关注【java进阶架构师】回复【架构】领取2019架构师完整视频一套。
转载说明:请务必注明来源(本文首发于公众号:【java进阶架构师】)