JavaのSpringフレームワークでAspect Oriented Programming「アスペクト志向言語」に触れる機会があり、かなり以前からある概念ですがはじめてでしたので試してみました。
難しそうな名前がついていますが、私の理解としてはオブジェクト指向言語の弱点を補うある意味苦肉の策的なもののような感じます。しかし処理が疎結合になりコードが見やすくなるメリットがあります。オブジェクトを横断的に共通の処理を注入するしくみで(Dependency Injection: 依存性の注入)、ログ出力処理などがわかりやすい例になります。
参考)
https://www.purin-it.com/spring-boot-aop
https://github.com/purin-it/java/tree/master/spring-boot-aop/demo
下記3つのJavaコードと、resources/application.properties、resources/templates/home.htmlをいろいろと変えながら内容を理解しました。
DemoApplication.java
1 2 3 4 5 6 7 8 9 10 |
package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } |
DemoController.java
1 2 3 4 5 6 7 8 9 10 11 12 |
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @Controller public class DemoController { private static Log log = LogFactory.getLog(DemoInvocation.class); @RequestMapping("/") public String home(){ log.debug("- home -"); return "home"; } } |
DemoInvocation.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
package com.example.demo; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect @Component public class DemoInvocation{ private static Log log = LogFactory.getLog(DemoInvocation.class); @Before("execution(* com.example.demo.*Controller.*(..))") public void beofreAccess(JoinPoint jp){ String signature = jp.getSignature().toString(); log.debug("Before : " + signature); } @After("execution(* com.example.demo.*Controller.*(..))") public void afterAccess(JoinPoint jp){ String signature = jp.getSignature().toString(); log.debug("After : " + signature); } @Around("execution(* com.example.demo.*Controller.*(..))") public Object arroundAccess(ProceedingJoinPoint jp){ Object returnObj = null; String signature = jp.getSignature().toString(); log.debug("Around1: " + signature); try { returnObj = jp.proceed(); }catch(Throwable t){ log.error("Error: ", t); } log.debug("Around2: " + signature); return returnObj; } } |
Webアクセスしたときにログを追加して、アクセスの前後で出力している様子をわかりやすくしました。
application.properties
server.port = 8080
logging.level.root = INFO
logging.level.com.example.demo = DEBUG
logging.file = C:/work/logs/demo.log
home.html
は任意の内容
ビルド
以前Groovy / Gradleをテストした環境を使いました。
build.gradleファイルがあるディレクトリで
gradle build
実行
cd build\libs
java -jar demo2-0.0.1-SNAPSHOT.jar
そして、Webブラウザでlocalhost:8080にアクセスします。
アノテーションを多用して制御するSpringフレームワークの勉強ができたことと、久しぶりにGradleを触って、その便利さをあらためて感じたテストでした。