AOP(Aspect Oriented Programming)

スプリングの重要機能の1つAOPをためす。
下にAOP概念図。

beans2.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    
    <bean id="man" class="jp.co.jjjjpppp.springtest.impl.Man">
        <property name="houseMaker">
            <ref bean="oobayashi"/>
        </property>
    </bean>
	
	<bean id="messageSource"
        class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basenames">
      <list>
        <value>jp.co.jjjjpppp.springtest.messages</value>
      </list>
    </property>
   </bean>
   
   <!-- イベントのキャッチ
   <bean id="iventCatcher" class="jp.co.jjjjpppp.springtest.impl.IventCatcher">
   </bean>
   -->
   
   <!-- AOPの設定 -->
   <bean id="loggingAdvice" class="jp.co.jjjjpppp.springtest.impl.LoggingAdvice">
   </bean>
   
   <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
   	<property name="target">
   		<ref local="man" />
   	</property>
	<property name="interceptorNames">
		<list>
			<value>advisor</value>
		</list>
   	</property>
   </bean>
   
   <bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
 		<property name="advice">
 			<ref local="loggingAdvice" />
 		</property>
		<property name="pointcut">
			<bean class="org.springframework.aop.support.JdkRegexpMethodPointcut">
				<property name="pattern">
					<value>.*</value>
				</property>
			</bean>
		</property>
   </bean>
   
  
</beans>
LoggingAdvice
package jp.co.jjjjpppp.springtest.impl;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.util.StopWatch;

public class LoggingAdvice implements MethodInterceptor {

    public Object invoke(MethodInvocation invocation) throws Throwable {
        
        String methodName = invocation.getMethod().getName();
        StopWatch sw = new StopWatch();
        
        sw.start(methodName);
        
        System.out.println("[LOG] METHOD: " + methodName + " is calling.");
        Object rtnObj = invocation.proceed();
        
        sw.stop();
        
        System.out.println("[LOG] METHOD: " + methodName + " was called.");
        System.out.println("[LOG] 処理時間: " + sw.getTotalTimeMillis() / 1000 + "秒");
        
        return rtnObj;
    }
}
Main (Proxyを使用するように変更)
/**
 * SpringFrameworkTest 2008/07/07
 */
package jp.co.jjjjpppp.springtest.impl;

import java.util.Locale;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		String[] config = { "src/configerFiles/beans.xml",
				"src/configerFiles/beans2.xml" };
		
		ConfigurableApplicationContext appCon = new FileSystemXmlApplicationContext(config);

		System.out.println(appCon.getMessage("startMessage", null, Locale.getDefault()));
		Man man = (Man) appCon.getBean("proxy");

		man.buyHouse();
		
		appCon.close();

	}

}
実行結果
2008/07/29 15:43:30 org.springframework.context.support.AbstractApplicationContext prepareRefresh
情報: Refreshing org.springframework.context.support.FileSystemXmlApplicationContext@b02e7a: display name [org.springframework.context.support.FileSystemXmlApplicationContext@b02e7a]; startup date [Tue Jul 29 15:43:30 JST 2008]; root of context hierarchy
2008/07/29 15:43:30 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
情報: Loading XML bean definitions from file [C:\eclipse\workSpace\SpringFrameworkTest\src\configerFiles\beans.xml]
2008/07/29 15:43:30 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
情報: Loading XML bean definitions from file [C:\eclipse\workSpace\SpringFrameworkTest\src\configerFiles\beans2.xml]
2008/07/29 15:43:30 org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
情報: Bean factory for application context [org.springframework.context.support.FileSystemXmlApplicationContext@b02e7a]: org.springframework.beans.factory.support.DefaultListableBeanFactory@16672d6
2008/07/29 15:43:31 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
情報: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@16672d6: defining beans [CC1,CC2,oobayashi,man,messageSource,loggingAdvice,proxy,advisor]; root of factory hierarchy
契約書を作成します。
2008/07/29 15:43:31 org.springframework.context.support.AbstractApplicationContext doClose
情報: Closing org.springframework.context.support.FileSystemXmlApplicationContext@b02e7a: display name [org.springframework.context.support.FileSystemXmlApplicationContext@b02e7a]; startup date [Tue Jul 29 15:43:30 JST 2008]; root of context hierarchy
2008/07/29 15:43:31 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
情報: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@16672d6: defining beans [CC1,CC2,oobayashi,man,messageSource,loggingAdvice,proxy,advisor]; root of factory hierarchy
[LOG] METHOD: buyHouse is calling.
六本木ヒルズを建築します。
★以下の会社に協力してもらいます。
習志野建設30人2000万
国土交通省4000人20兆円
★以下のステークスホルダーが存在します。
下請け
★以下の工法で建築します
骨組み重視
[LOG] METHOD: buyHouse was called.
[LOG] 処理時間: 0秒

ぬぬ。ログの出力順番が変わった。AppContextが閉じられてからメソッドが実行されているようだ。プロキシとイベントキャッチ処理を併用する場合要注意かも。