今回は、Spring MVC上のサンプルプログラムで、AOP(Aspect Oriented Programming、アスペクト指向プログラミング)でログ出力する処理を追加してみたので、そのサンプルプログラムを共有する。
前提条件
下記記事の実装が完了していること。
Spring MVCでMyBatisによるOracle連携処理を実装してみた今回は、Spring MVC上で、MyBatisによるOracle連携処理を行うプログラムを作成してみたので、そのサンプルプログラムを共...
サンプルプログラムの作成
作成したサンプルプログラムの構成は以下の通り。
なお、上記の赤枠は、「前提条件」のプログラムから変更したプログラムである。
pom.xmlに追加した内容は以下の通りで、AOPの実装に必要なライブラリを追加している。
<!-- AOP --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${org.springframework-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${org.springframework-version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${org.aspectj-version}</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2</version> </dependency>
また、servlet-context.xmlの内容は以下の通りで、先頭のbeans:beansタグにAOPの名前空間を追加すると共に、aop:aspectj-autoproxyタグを追加している。
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure --> <!-- Enables the Spring MVC @Controller programming model --> <annotation-driven /> <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory --> <resources mapping="/resources/**" location="/resources/" /> <!-- Thymeleafの読み込み --> <beans:bean id="templateResolver" class="org.thymeleaf.spring3.templateresolver.SpringResourceTemplateResolver"> <beans:property name="prefix" value="/WEB-INF/templates/" /> <beans:property name="suffix" value=".html" /> <beans:property name="templateMode" value="HTML5" /> <beans:property name="characterEncoding" value="UTF-8" /> </beans:bean> <beans:bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine"> <beans:property name="templateResolver" ref="templateResolver" /> </beans:bean> <beans:bean class="org.thymeleaf.spring3.view.ThymeleafViewResolver"> <beans:property name="templateEngine" ref="templateEngine" /> <beans:property name="characterEncoding" value="UTF-8" /> </beans:bean> <!-- メッセージリソースの読み込み --> <beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <beans:property name="basename" value="classpath:messages" /> <beans:property name="defaultEncoding" value="UTF-8" /> </beans:bean> <!-- DB接続先の読み込み --> <beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <beans:property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> <beans:property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" /> <beans:property name="username" value="USER01" /> <beans:property name="password" value="USER01" /> </beans:bean> <!-- MyBatisのMapperオブジェクトの生成 --> <beans:bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <beans:property name="dataSource" ref="dataSource" /> <beans:property name="mapperLocations" value="classpath*:com/example/demo/*.xml" /> </beans:bean> <beans:bean id="userDataMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <beans:property name="mapperInterface" value="com.example.demo.UserDataMapper" /> <beans:property name="sqlSessionFactory" ref="sqlSessionFactory" /> </beans:bean> <!-- AOP使用設定の追加 --> <aop:aspectj-autoproxy /> <context:component-scan base-package="com.example.demo" /> </beans:beans>
さらに、ログ出力するAOPのクラスは以下の通りで、Spring Bootの場合と同じように@Aspectアノテーション等を利用していて、コントローラクラスの呼出前後にログを出力する仕組みになっている。
package com.example.demo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect @Component public class DemoInvocation { //ログ出力のためのクラス private static final Logger logger = LoggerFactory.getLogger(DemoInvocation.class); /** * Beforeアノテーションにより、指定したメソッドの前に処理を追加する * Beforeアノテーションの引数には、Pointcut式 execution(戻り値 パッケージ.クラス.メソッド(引数))を * 指定し、ここではControllerクラスの全メソッドの実行前にログ出力するようにしている * * @param jp 横断的な処理を挿入する場所 */ @Before("execution(public String com.example.demo.*Controller.*(..))") public void startLog(JoinPoint jp){ //開始ログを出力 String signature = jp.getSignature().toString(); logger.info("開始ログ : " + signature); } /** * Afterアノテーションにより、指定したメソッドの前に処理を追加する * Afterアノテーションの引数には、Pointcut式を指定 * * @param jp 横断的な処理を挿入する場所 */ @After("execution(public String com.example.demo.*Controller.*(..))") public void endLog(JoinPoint jp){ //終了ログを出力 String signature = jp.getSignature().toString(); logger.info("終了ログ : " + signature); } }
その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-mvc-web-aop/demo
サンプルプログラムの実行結果
サンプルプログラムを実行したときの画面・ログの内容は、以下の通り。
1) サーバーを起動後、Webブラウザ上で「http://(サーバー名):(ポート番号)/(プロジェクト名)/」とアクセスすると、以下の画面が表示されるので、「検索」ボタンを押下
3) このときのコンソールログは以下の通りで、下記赤枠のログがDemoInvocation.javaによって出力されることが確認できる。
要点まとめ
- Spring MVCプロジェクトでAOPを利用するには、AOP接続に必要なライブラリ(spring-context, spring-aop, aspectjweaver, cglib)を追加し、servlet-context.xmlに、先頭のbeans:beansタグにAOPの名前空間を追加すると共に、aop:aspectj-autoproxyタグを追加する必要がある。