2008/04/16からのアクセス回数 7559 AopNameSpaceとは何か †Spring 2.0の特徴は、
ことです。 AopNameSpaceでは、普通のオブジェクト(以下POJOオブジェクトと呼びます)をAspectの Adviceとして使用することができます。 AopNameSpaceを使用するとAutoProxyCreatorは使用できないことに注意してください。 準備 †AopNameSpaceを使用するには、
が必要です。 いつものようにMVN Repositoryで検索すると、以下のようなdependecyタグが見つかりました。 <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.5.4</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.5.4</version> </dependency> これをpom.xmlに追加して、以下のコマンドを実行してください。 $ rm .project .classpath $ mvn eclipse:eclipse -DdownloadSources=true AopNameSpaceの例題 †AopNameSpaceを使った例を順を追って作成していきましょう。 POJOオブジェクト †Adviceとして使用するPOJOオブジェクトクラス(POJOAdvice)を以下のように定義します。 package org.springframework.showcase.aop; public class POJOAdvice { public void a() { System.out.println("a called"); } public void b(Long id) { System.out.println("b(" + id +") called"); } }
AOP定義ファイル †AopNameSpaceを使った定義ファイルは他のBean定義ファイルと別ファイルにすると 機能が切り分けられます。 aop-def.xmlは、以下のようになります。 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> <bean id="pojoAdvice" class="org.springframework.showcase.aop.POJOAdvice" /> <aop:config> <aop:aspect ref="pojoAdvice"> <aop:before method="a" pointcut="execution(* *.findAll(..))" /> <aop:before method="b" pointcut="execution(* org.springframework.showcase.coverc.service.GenericHibernateDao.findById(..)) and args(id)" /> </aop:aspect> </aop:config> </beans>
'<aop:config>では、<aop:before>の他に以下の要素(タグ)が使用できます。
'<aop:before>に戻って
します。 AspectJのpointcutは、 execution ( <戻り値のタイプ> <クラスパス>.<メソッド名>( [ <引数のタイプ> ] ) ) の形式で記述します。 aの場合のpointcutを見てみると pointcut="execution(* *.findAll(..))" とありますが、型、クラスパスに関係なくfindAllという名前のメソッドにpointcutを設定する 指定です。 次にbの場合のpointcutを見ると pointcut="execution(* org.springframework.showcase.coverc.service.GenericHibernateDao.findById(..)) and args(id)" and args(id)でfindByIdの引数idをbの呼び出しに渡すことを指定します。 web.xmlの変更 †aop-def.xmlを追加するために、web.xmlに以下のcontext-paramタグを追加します。 <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/applicationContext.xml /WEB-INF/aop-def.xml </param-value> </context-param> applicationContext.xmlの変更 †前回のDefaultAdvisorAutoProxyCreatorを使ったAOPと共存できないので、applicationContext.xmlを 以下のように変更します。 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <bean id="recipeManager" class="org.springframework.showcase.coverc.service.StubRecipeDaoManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>org.postgresql.Driver</value> </property> <property name="url"> <value>jdbc:postgresql://localhost/springdb</value> </property> <property name="username"> <value>spring</value> </property> <property name="password"> <value>spring</value> </property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop> </props> </property> <property name="mappingDirectoryLocations"> <list> <value>classpath:/org/springframework/showcase/coverc/domain</value> </list> </property> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean> </beans> 例題の実行 †maven jettyプラグインを使って例題を実行します。 $ mvn jetty:run 次にブラウザーで http://localhost:8080/mvc-convention/ と入力すると a called a called と表示されます。これは、RecipeManagerのfindAllとGenericHibernateDaoのfindAllの2カ所に pointcutが設定されたからです。 次に、ブラウザのaddリンクをクリックして「test」を入力した後、Save Changeボタンを押してください。 testがリストに追加されましたが、testのdeleteリンクをクリックしてください。 b(4) called a called a called とb(4) calledが表示されます。bは、 org.springframework.showcase.coverc.service.GenericHibernateDao.findById とクラスパスを指定しているので1回だけ表示されます。 ログ出力との併用 †AopNameSpaceを使ったAOPでは、引数を明示的に指定する必要があり、ログ出力のような チェックプリントのメソッドを実行することができません。 チェックプリントは、デバッガでは追えない並行処理のデバッグに有効な手段です。 ここでは、ログ出力とAopNameSpaceの併用の方法について説明します。 チェックプリントを出力したいBeanをProxyFactoryBeanでラップすることで 指定したBeanにログ出力機能を加えることができます。
<bean id="enterMethodLogAdvice" class="org.springframework.showcase.aop.EnterMethodLogAdvice"/> <bean id="leaveMethodLogAdvice" class="org.springframework.showcase.aop.LeaveMethodLogAdvice"/> <bean id="logBase" abstract="true"> <property name="interceptorNames"> <list> <value>enterMethodLogAdvice</value> <value>leaveMethodLogAdvice</value> </list> </property> </bean> <bean id="recipeManager" class="org.springframework.aop.framework.ProxyFactoryBean" parent="logBase"> <property name="target"> <bean class="org.springframework.showcase.coverc.service.StubRecipeDaoManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> </property> </bean> 実行例 †先ほどと同様に実行すると、 a called enter findAll args=() a called leave findAll return=[org.springframework.showcase.coverc.domain.Recipe@9ab468, org.springframework.showcase.coverc.domain.Recipe@a06db5, org.springframework.showcase.coverc.domain.Recipe@82aacf] -- 途中省略 enter save args=(org.springframework.showcase.coverc.domain.Recipe@fbe09b) leave save return=null a called enter findAll args=() a called leave findAll return=[org.springframework.showcase.coverc.domain.Recipe@82c6dc, org.springframework.showcase.coverc.domain.Recipe@cdb92b, org.springframework.showcase.coverc.domain.Recipe@37bc9e, org.springframework.showcase.coverc.domain.Recipe@403477] enter findById args=(4) b(4) called leave findById return=org.springframework.showcase.coverc.domain.Recipe@108172 enter delete args=(org.springframework.showcase.coverc.domain.Recipe@108172) leave delete return=null a called enter findAll args=() a called leave findAll return=[org.springframework.showcase.coverc.domain.Recipe@6b2d99, org.springframework.showcase.coverc.domain.Recipe@7ec7b9, org.springframework.showcase.coverc.domain.Recipe@6a56f0] のようにログ出力とAopNameSpaceの出力の両方が出ています。 Spring-MVC/ステップ・バイ・ステップ/AOPの追加の 今回使用したファイルは、以下にあります。 コメント †この記事は、 皆様のご意見、ご希望をお待ちしております。 Tweet |