Spring AOPとは
Spring Frameworkにおいて、DI(Dependency Injection、依存性注入)と並び重要な根幹技術となっているのが「AOP」というものです。
AOPは、「Aspect Oriented Programming(アスペクト指向プログラミング)」の略です。アスペクトというのは、一般に「横断的関心事」と呼ばれるものです。
環境
- spring
- java8
- Log4j
Spring AOPのアノテーション用語
1.@Aspect
@Aspectをクラスにつけることで、そのクラスはAspectとして認識されます。
2.@Pointcut
横断的な処理を挿入する場所(メソッド)を指定する。
3.@Before
対象のメソッドの処理前に実行されるAdviceです。
4.@After
対象のメソッドの処理結果に関わらず、必ず実行されるAdviceです。
5.@AfterReturning
対象のメソッドの処理が正しく終了した場合にのみ実行されるAdviceです。
6.@AfterThrowing
対象のメソッドの処理中に例外が発生した場合にのみ実行されるAdviceです。
実装デモ
package aspect.log;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/** ログ出力のアスペクトクラス. */
@Aspect
@Component
public class LoggingAspect {
private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);
/** publicメソッドのポイントカット. システムエラーログ出力*/
@Pointcut("execution(public * *(..))")
private void publicLog() {}
/** daoパッケージのポイントカット. db操作ログ出力 */
@Pointcut("within(app.dao..*)")
private void dbLog() {}
/** webパッケージのポイントカット. リクエスト、レスポンスなどのログ出力*/
@Pointcut("within(app.web..*)")
private void webLog() {}
/**
* メソッド実行前にログ出力します.
*
* @param jp ジョインポイント
*/
@Before("publicLog() && (dbLog() || webLog())")
public void dobefore(JoinPoint jp) {
Signature sig = jp.getSignature();
String args = "無し";
if(jp.getArgs() != null && jp.getArgs().length > 0 ) {
args = Arrays.toString(jp.getArgs());
}
logger.info("【操作開始】" +"メソッド:"+sig.getDeclaringTypeName() + "."+sig.getName()+"#入力パラメータ:"+ args);
}
/**
* メソッド実行後にログ出力します.
*
* @param jp ジョインポイント
*/
@AfterReturning(pointcut="publicLog() && (dbLog() || webLog())",returning="returnValue")
public void doAfterReturning(JoinPoint jp,Object returnValue) {
Signature sig = jp.getSignature();
logger.info("【操作終了】"+"メソッド:"+sig.getDeclaringTypeName() + "."+sig.getName()+"#戻り値:" + returnValue);
}
/**
* エラーが発生した場合、ログ出力します.
*
* @param jp ジョインポイント
*/
@AfterThrowing (pointcut="publicLog() && (dbLog() || webLog())",throwing="ex")
public void doAfterThrowing(JoinPoint jp,Exception ex) {
Signature sig = jp.getSignature();
StringWriter erMessage=new StringWriter();
ex.printStackTrace(new PrintWriter(erMessage));
logger.info("【エラー】" + "メソッド:"+sig.getDeclaringTypeName() + "."+sig.getName()+"#エラーメッセージ:" + erMessage.toString());
}
}
最後に
最後まで読んでいただき、ありがとうございます。
参考:
https://docs.spring.io/spring/docs/5.0.5.RELEASE/spring-framework-reference/core.html#aop
https://iikanji.hatenablog.jp/entry/2018/04/26/204324