Springのaop浅析

13086 ワード

spring aopプログラミング全体について個人的に理解する
つまり、aspectでpointcutを使用してブロックするjoinpointを定義し、weavingの過程でtargetオブジェクトにaspectで定義したadviceを付加する行為です.
まずspring実装エージェントの2つの方法を見てみましょう:jdkダイナミックエージェントとcglibエージェント(説明が必要な場所コードに説明があります)
テストクラスSpringTestProxy.java
 
package com.undergrowth.test;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.List;

import org.aspectj.weaver.NewConstructorTypeMunger;
import org.junit.Test;

import com.undergrowth.utils.ProxyObjectInstance;

/*
 *       Spring Proxy       
 * 1.jdk dynamic proxy(jdk       )
 * 2.cglib proxy(   jar  cglib  )
 * 
 * 
 */

public class SpringTestProxy {

	@Test
	public void test() {
		ProxyObjectInstance proxyObjectInstance=new ProxyObjectInstance();
		List arrayList=(List) proxyObjectInstance.createJdkProxyObject(new ArrayList());
		System.out.println(arrayList.add(3));
		arrayList=(List) proxyObjectInstance.createCglibObject(new ArrayList());
		System.out.println(arrayList.add(3));
	}

}

コンソール出力:
      
      
true
  cglib     
  cglib     
true

ツールクラス
ProxyObjectInstance.java
package com.undergrowth.utils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;


/*
 *      jdk      cglib               
 */
public class ProxyObjectInstance implements InvocationHandler,MethodInterceptor{
	
	private Object target;
	
	//  jdk                             
	//                InvocationHandler                            (invoke  )
	public Object createJdkProxyObject(Object targetObject)
	{
		this.target=targetObject;
		Class targetClass=this.target.getClass();
		return Proxy.newProxyInstance(targetClass.getClassLoader(),targetClass.getInterfaces(), this);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		//               
		System.out.println("      ");
		//         
		Object returnValue=method.invoke(target, args);
		System.out.println("      ");
		return returnValue;
	}
	
	//  cglib                         
	//            final           MethodInterceptor
	//                           (intercept  )
	public Object createCglibObject(Object targetObject)
	{
		this.target=targetObject;
		Enhancer enhancer=new Enhancer();
		enhancer.setSuperclass(target.getClass());
		enhancer.setCallback(this);
		return enhancer.create();
	}

	@Override
	public Object intercept(Object arg0, Method arg1, Object[] args,
			MethodProxy method) throws Throwable {
		//               
		System.out.println("  cglib     ");
		//         
		Object returnValue=method.invoke(target, args);
		System.out.println("  cglib     ");
		return returnValue;
	}
}

springの2つのエージェント方式の結果は一致しており、ターゲットオブジェクトにインタフェースがある場合、jdkを使用する動的エージェントは、ターゲットオブジェクトにインタフェースがない場合、cglibエージェントを使用して実現される.
次にspringのaopプログラミングの2つの方式の注釈とxmlファイルの方式を見てみましょう
まず注釈の仕方を見てみましょう
テストコード:
SpringTestAspectJ.java
package com.undergrowth.test;

import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.undergrowth.aspect.test.bean.TargetObject;

/*
 *      aspectj     spring aop  
 
 *1.         spring aspectj     
 *2.  @Aspect      
 *
 *     xml     
 *    xml      pojo       aspect   
 *
 *
 *
 **   
 * Weaving(  )---linking aspects with other application types or objects 
 * to create an advised object. 
 *                               
 *   spring      ,   @Transactional       ,spring       aop            
 *     、               、                         
 * 
 * 
 *     spring aop       
 *    aspect    pointcut        joinpoint,   weaving    ,
 *  target      aspect     advice   
 * 
 */
public class SpringTestAspectJ {
	
	private static  AbstractApplicationContext aac;
	
	@BeforeClass
	public static void beforeClass()
	{
		aac=new ClassPathXmlApplicationContext("applicationContext.xml");
	}
	
	@Test
	public void test()
	{
		TargetObject targetObject= (TargetObject) aac.getBean("targetObject");
		targetObject.say("spring aop annotation   ");
	}
}

プロファイルアプリケーションContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
	           http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
    
	<!--  enable Spring support for configuring Spring AOP based on @AspectJ aspects, 
	 and autoproxying beans based on whether or not they are advised by those aspects.
	                         aspectj               java                   
	  -->
	 
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
	 <bean id="aspectDefinition" class="com.undergrowth.aspect.AspectDefinition"></bean>
    
   <!--      xml        java  com.undergrowth.aspect.AspectXml     aspect 
     	                
   -->
  <!--   <bean id="aspectXml" class="com.undergrowth.aspect.AspectXml"></bean>
    <aop:config>
     <aop:aspect ref="aspectXml">
       <aop:pointcut expression="execution(* com.undergrowth.aspect.test.bean..*.*(..))" id="pointcut"/>
       <aop:before method="beforeAdvice" pointcut-ref="pointcut"/>
       <aop:after-returning method="afterReturn"  pointcut-ref="pointcut"/>
     </aop:aspect>
    </aop:config> -->
   
    <bean id="targetObject" class="com.undergrowth.aspect.test.bean.TargetObject"></bean>

</beans>

切断ファイルjava
package com.undergrowth.aspect;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

//                     java 
@Aspect
public class AspectDefinition {
	//     --            
	@Pointcut("execution(* com.undergrowth.aspect.test.bean..*.*(..))")
	private void interceptorDefini(){}
	
	//    
	@Before("interceptorDefini()")
	public void beforeAdvice()
	{
		System.out.println("    ");
	}
	
	//                    
	@AfterReturning("interceptorDefini()")
	public void afterReturn()
	{
		System.out.println("    ");
	}
}

ターゲットオブジェクトjava
package com.undergrowth.aspect.test.bean;

/*
 *     
 */

public class TargetObject {

		public void say(String sayWhat)
		{
			System.out.println("     :"+sayWhat);
		}
}

テストメソッドの実行
コンソール出力:
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    
     :spring aop annotation   
    

以上,注釈を用いてspring sopを実現する.
プロファイルアプリケーションContextを変更する.JAvaは以下の通りです
<?xml version="1.0" encoding="UTF-8"?>
<beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
	           http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
    
	<!--  enable Spring support for configuring Spring AOP based on @AspectJ aspects, 
	 and autoproxying beans based on whether or not they are advised by those aspects.
	                         aspectj               java                   
	  -->
	 
	<!-- <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
	 <bean id="aspectDefinition" class="com.undergrowth.aspect.AspectDefinition"></bean> -->
    
   <!--      xml        java  com.undergrowth.aspect.AspectXml     aspect 
     	                
   -->
    <bean id="aspectXml" class="com.undergrowth.aspect.AspectXml"></bean>
    <aop:config>
     <aop:aspect ref="aspectXml">
       <aop:pointcut expression="execution(* com.undergrowth.aspect.test.bean..*.*(..))" id="pointcut"/>
       <aop:before method="beforeAdvice" pointcut-ref="pointcut"/>
       <aop:after-returning method="afterReturn"  pointcut-ref="pointcut"/>
     </aop:aspect>
    </aop:config>
   
    <bean id="targetObject" class="com.undergrowth.aspect.test.bean.TargetObject"></bean>

</beans>

純java類AspectXml.java
package com.undergrowth.aspect;

/*
 *      xml            aspect
 */

public class AspectXml {
	
	public void beforeAdvice()
	{
		System.out.println("  xml       ");
	}
	
	public void afterReturn()
	{
		System.out.println("  xml       ");
	}
}

テストメソッドコンソールの出力を実行します.
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
  xml       
     :spring aop annotation   
  xml       

総じてspringのaop
個人的には事務管理の1つを使うのは本当にとても便利だと感じて、多くのコードを簡略化しましたもちろん私のレベルは限られていて、もっと多くの機能があるかもしれません.私はまだ上のテストの例が比較的に簡単に詳しく書いてあることに気づいていません.springの公式ドキュメントには記録学習の足どりを説明して努力し続けています.
追加:pointcut式のいくつかの解釈
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
          throws-pattern?)

All parts except the returning type pattern (ret-type-pattern in the snippet above), name pattern, and parameters pattern are optional. The returning type pattern determines what the return type of the method must be in order for a join point to be matched. Most frequently you will use  *  as the returning type pattern, which matches any return type. A fully-qualified type name will match only when the method returns the given type. The name pattern matches the method name. You can use the  *  wildcard as all or part of a name pattern. The parameters pattern is slightly more complex:  ()  matches a method that takes no parameters, whereas  (..)  matches any number of parameters (zero or more). The pattern  (*)  matches a method taking one parameter of any type,  (*,String)  matches a method taking two parameters, the first can be of any type, the second must be a String. Consult the  Language Semantics  section of the AspectJ Programming Guide for more information.
the execution of any method defined in the service package or a sub-package:
execution(* com.xyz.service..*.*(..))