第三章AOP Java APIによる切断面の作成


前に補強を使用したとき,補強はターゲットクラスのすべての方法に織り込まれることが分かった.ターゲットクラスの特定の方法に強化を織り込む場合,ターゲット接続点の位置決めに接点を用いる必要がある.次に、カットポイントと強化によってカットを生成することができます.
3.4.1接点タイプ
静的メソッド接点:org.springframework.aop.support.StaticMethodMatcherPointcut
動的メソッド接点:org.springframework.aop.support.DynamicMethodMatcherPointcut
注記接点:org.springframework.aop.support.annotation.AnnotationMatchingPointcut
式接点:org.springframework.aop.support.ExpressionPointcut
プロセス接点:org.springframework.aop.support.ControlFlowPointcut
3.4.2静的方法で接面を一致させる
org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor
a、強化クラス
ここで使用するのは3.3です.2の前面拡張:
http://blog.csdn.net/p_3er/article/details/9239925
ただし、UserDaoImplには2つのメソッド、saveメソッド、deleteメソッドがあります.次にsaveメソッドにフェースを構成します.
b、接面類継承S e c M t h o d MatcherPointcutAdvisor
public class StaticAdvisor extends StaticMethodMatcherPointcutAdvisor {
	/*
	 *         
	 */
	public boolean matches(Method method, Class<?> clazz) {
		return method.getName().equals("save");
	}

	/*
	 *   StaticMethodMatcherPointcut getClassFilter()
	 *          
	 */
	public ClassFilter getClassFilter() {
		ClassFilter classFilter = new ClassFilter() {
			public boolean matches(Class<?> clazz) {
				return UserDaoImpl.class.isAssignableFrom(clazz);
			}
		};
		return classFilter;
	}
}

c、構成
<!--   Bean -->
	<bean id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean>
	
	<!--   Bean -->
	<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>
	
	<!--      。p:advice-ref        -->
	<bean id="staticAdvisor" class="cn.framelife.spring.advisor.StaticAdvisor" p:advice-ref="userDaoBeforeAdvice"></bean>
	
	<!-- 
		       
		p:interceptorNames    ,      
	-->
	<bean id="paramProxy" 
		class="org.springframework.aop.framework.ProxyFactoryBean"
		p:interceptorNames="staticAdvisor"
		p:proxyTargetClass="true" />	
	<!--        -->
	<bean id="userDaoProxy" parent="paramProxy" p:target-ref="userDao"></bean>

d、テスト
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		UserDao userDao = (UserDao) context.getBean("userDaoProxy");
		//UserDaoImpl      ,save      ,delete    
		userDao.save();
		System.out.println("----------");
		userDao.delete();

e、結果
      :save
    ...
----------
    ...

3.4.3静的正規表現メソッド断面の構成
この方法は自分でうどん類を書く必要はありません.
       org.springframework.aop.support.RegexpMethodPointcutAdvisorは正規表現法が一致する接面実装クラスである.
a、強化クラス
ここで使用するのは3.3です.2の前面拡張:
http://blog.csdn.net/p_3er/article/details/9239925
b、配置
<!--   Bean -->
	<bean id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean>
	
	<!--   Bean -->
	<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>
	
	<!-- 
		    Bean 
		patterns                        
			         ,          。 : cn.framelife.spring.dao.impl.UserDaoImpl.delete()
		<value>.*delete</value>      
	-->
	<bean id="regexpAdvisor" 
		class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
		p:advice-ref="userDaoBeforeAdvice">
		<property name="patterns">
			<list>
				<value>.*delete</value>
			</list>
		</property>
	</bean>
	
	<!-- 
		      
	-->
	<bean id="regexpProxy" 
		class="org.springframework.aop.framework.ProxyFactoryBean"
		p:interceptorNames="regexpAdvisor"
		p:target-ref="userDao"
		p:proxyTargetClass="true" />	

c、テスト
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		UserDao userDao = (UserDao) context.getBean("regexpProxy");
		userDao.save();
		System.out.println("----------");
		userDao.delete();

d、結果
    ...
----------
      :delete
    ...

一般的な正規表現規則
1、.*set.*すべてのクラスのsetを接頭辞とする方法を表します.如:com.abc.UserDao.setName().
2、com\.abc\.service\..*表示com.abc.service.すべてのクラスのすべてのメソッドをパッケージします.
Com.abc.service.a.User.setName()
Com.abc.service.UserService.save()
3、com\.abc\.service\..*Service\..*表示com.abc.サービスパッケージの下にサービスで終わるクラスのすべての方法.如:com.abc.service.UserService.save()
4、com\.abc\.service\..*Service\.save.+saveを接頭辞とするすべての方法を一致させ、save後に1つ以上の文字を持つ必要があります.如:com.abc.service.UserService.saveUser()
3.4.4ダイナミックカット
org.springframework.aop.support.D y n a m i c MethodMatcherPointcutクラスには静的接点検査の方法もあれば,動的接点検査の方法もある.ダイナミック接点チェックはパフォーマンスに大きな影響を及ぼすため、実行時にターゲットクラスの各メソッドを毎回チェックすることは避けなければなりません.
Spring動的接点をチェックするメカニズム:エージェントの作成時にターゲットクラスの各接続点に対して静的接点検査を行い、静的接点検査だけで接続点が一致していないことを知ることができ、実行期間中に動的検査を行わない.静的接点チェックが一致している場合は、実行期間中に動的メソッドチェックが行われます.
動的接面は、D y n a m i c MethodMatcherPointcut接点と組み合わせたD e f a u ltPointcutAdvisor接面クラスによって生成されます.主に接続点メソッドのパラメータです.
a、強化クラス
ここで使用するのは3.3です.2の前面拡張:
http://blog.csdn.net/p_3er/article/details/9239925
ただ、UserDaoImplにはoutメソッドが1つ増えており、パラメータが付いています.
b、接点類継承DynamicMethodMatcherPointcut
public class DynamicPointcut extends DynamicMethodMatcherPointcut {
	// list       
	private List<String> specialNames = new ArrayList<String>();
	
	public DynamicPointcut(){
		specialNames.add("aa");
		specialNames.add("bb");
	}
	/*
	 *           
	 */
	public ClassFilter getClassFilter() {
		
		return new ClassFilter() {
			@Override
			public boolean matches(Class<?> targetClass) {
				System.out.println("  getClassFilter    :"+targetClass.getName());
				return UserDaoImpl.class.isAssignableFrom(targetClass);
			}
		};
	}

	/*
	 *           
	 */
	public boolean matches(Method method, Class<?> targetClass) {
		System.out.println("  matches(method,targetClass)      :"+targetClass.getName()+"--"+method.getName());
		return method.getName().equals("out");
	}


	/*
	 *           
	 */
	public boolean matches(Method method, Class<?> targetClass, Object[] args) {
		System.out.println("  matches(method,targetClass)      :"+targetClass.getName()+"--"+method.getName()+"   ");
		String name = (String)args[0];
		return specialNames.contains(name);
	}
}

c、構成
<!--   Bean -->
	<bean id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean>

	<!--   Bean -->
	<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>
	
	
	<!--    -->
	<bean id="dynamicAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
		<!--      -->
		<property name="pointcut">
			<bean class="cn.framelife.spring.pointcut.DynamicPointcut"></bean>
		</property>
		<!--      -->
		<property name="advice" ref="userDaoBeforeAdvice"></property>
	</bean>
	
	<!-- 
		     
	-->
	<bean id="dynamicProxy" 
		class="org.springframework.aop.framework.ProxyFactoryBean"
		p:interceptorNames="dynamicAdvisor"
		p:target-ref="userDao"
		p:proxyTargetClass="true" />	

d、テスト
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		UserDao userDao = (UserDao) context.getBean("dynamicProxy");
		//UserDaoImpl     out  ,     。
		System.out.println("----------");
		userDao.save();
		System.out.println("----------");
		userDao.out("aa");
		System.out.println("----------");
		userDao.out("1111");
		System.out.println("----------");

e、結果
  getClassFilter    :cn.framelife.spring.dao.impl.UserDaoImpl
  matches(method,targetClass)      :cn.framelife.spring.dao.impl.UserDaoImpl--out
  getClassFilter    :cn.framelife.spring.dao.impl.UserDaoImpl
  matches(method,targetClass)      :cn.framelife.spring.dao.impl.UserDaoImpl--save
  getClassFilter    :cn.framelife.spring.dao.impl.UserDaoImpl
  matches(method,targetClass)      :cn.framelife.spring.dao.impl.UserDaoImpl--delete
  getClassFilter    :cn.framelife.spring.dao.impl.UserDaoImpl
  matches(method,targetClass)      :cn.framelife.spring.dao.impl.UserDaoImpl--clone
  getClassFilter    :cn.framelife.spring.dao.impl.UserDaoImpl
  matches(method,targetClass)      :cn.framelife.spring.dao.impl.UserDaoImpl--toString
----------
  getClassFilter    :cn.framelife.spring.dao.impl.UserDaoImpl
  matches(method,targetClass)      :cn.framelife.spring.dao.impl.UserDaoImpl--save
    ...
----------
  getClassFilter    :cn.framelife.spring.dao.impl.UserDaoImpl
  matches(method,targetClass)      :cn.framelife.spring.dao.impl.UserDaoImpl--out
  matches(method,targetClass)      :cn.framelife.spring.dao.impl.UserDaoImpl--out   
      :out
out     :aa
----------
  matches(method,targetClass)      :cn.framelife.spring.dao.impl.UserDaoImpl--out   
out     :1111
----------

3.4.5プロセススライス
1つのクラスのいずれかのメソッドがターゲットクラスの2つのメソッドを使用すると、プロセスフェースを使用して両方のメソッドに強化を積むことができます.
たとえば、UserServiceImplクラス(使用クラス)operateメソッドでUserDaoImpl(ターゲットクラス)を使用する2つのメソッドです.
プロセススライスは、ControlFlowPointcutを使用してDefaultPointcutAdvisorと結合して形成されます.
a、強化クラス
ここで使用するのは3.3です.2の前面拡張:
http://blog.csdn.net/p_3er/article/details/9239925
ただし、UserDaoImplには2つのメソッド、saveメソッド、deleteメソッドがあります.次にsaveメソッドにフェースを構成します.
b、UserServiceImplクラス
public class UserServiceImpl implements UserService {
	private UserDao userDao;
	
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	public void addUser() {
		userDao.save();
	}

	@Override
	public void operate() {
		//       userDao     
		userDao.delete();
		userDao.save();
	}
}

c、構成
<!--   Bean -->
	<bean id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean>

	<!--   Bean -->
	<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>
	
	<!--    -->
	<bean id="controlFlowPointcut" class="org.springframework.aop.support.ControlFlowPointcut">
		<!--          -->
		<constructor-arg type="java.lang.Class" value="cn.framelife.spring.service.impl.UserServiceImpl"></constructor-arg>
		<!--           -->
		<constructor-arg type="java.lang.String" value="operate"></constructor-arg>
	</bean>
	
	<!--    -->
	<bean id="controlFlowAdvisor" 
		class="org.springframework.aop.support.DefaultPointcutAdvisor"
		p:pointcut-ref="controlFlowPointcut"
		p:advice-ref="userDaoBeforeAdvice"/>	
	
	<!-- 
		     
	-->
	<bean id="controlFlowProxy" 
		class="org.springframework.aop.framework.ProxyFactoryBean"
		p:interceptorNames="controlFlowAdvisor"
		p:target-ref="userDao"
		p:proxyTargetClass="true" />
	
	<!--        Bean  Spring   -->
	<bean id="userService" class="cn.framelife.spring.service.impl.UserServiceImpl">
		<property name="userDao" ref="controlFlowProxy"></property>
	</bean>

d、テスト
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		UserService userService = (UserService) context.getBean("userService");
		userService.operate();
		System.out.println("----------------");
		userService.addUser();

e、結果
      :delete
    ...
      :save
    ...
----------------
    ...

3.4.6複合断面
前の例では、私たちが定義したうどんは1つの接点しかありません.接続点を決定するには、1つの切断面に複数の切断点、すなわち複数の条件が必要になる場合があります.複数の接点が1つの接点を構成し、このような接点は複合接点である.複合接点に補強された接面を加えて複合接面と呼ぶ.
a、強化クラス
ここで使用するのは3.3です.2の前面拡張:
http://blog.csdn.net/p_3er/article/details/9239925
b.一般クラスにPointcutを取得する方法
public class MyPointcut {
//  Pointcut     get  
	public Pointcut getMyComposablePointcut(){
		//        
		ComposablePointcut cp = new ComposablePointcut();

		//        (  :   、     )      3.4.5  UserServiceImpl 
		Pointcut pt1 = new ControlFlowPointcut(UserServiceImpl.class,"operate");
		
		//          
		Pointcut pt2 = new StaticMethodMatcherPointcut() {
			public boolean matches(Method method, Class<?> clazz) {
				return UserDaoImpl.class.isAssignableFrom(clazz)&&method.getName().equals("delete");
			}
		};

		//          .
		return cp.intersection(pt1).intersection(pt2);
	}
}

c、構成
<!--   Bean -->
	<bean id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean>

	<!--   Bean -->
	<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>
	
	<!--       -->
	<bean id="myPoincut" class="cn.framelife.spring.pointcut.MyPointcut"></bean>
	
	<!-- 
		  
		p:pointcut #{ myPoincut.myComposablePointcut}   MyPointcut getMyComposablePointcut     
	-->
	<bean id="composableAdvisor" 
		class="org.springframework.aop.support.DefaultPointcutAdvisor"
		p:pointcut="#{ myPoincut.myComposablePointcut}"
		p:advice-ref="userDaoBeforeAdvice"/>	
	
	<!-- 
		     
	-->
	<bean id="composableProxy" 
		class="org.springframework.aop.framework.ProxyFactoryBean"
		p:interceptorNames="composableAdvisor"
		p:target-ref="userDao"
		p:proxyTargetClass="true" />
	
	<!--        Bean  Spring   -->
	<bean id="userService" class="cn.framelife.spring.service.impl.UserServiceImpl">
		<property name="userDao" ref="composableProxy"></property>
	</bean>

d、テスト
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		UserService userService = (UserService) context.getBean("userService");
		userService.operate();

e、結果
      :delete
    ...
    ...

3.4.7誘導切断面
a、使用3.3.6紹介強化の中身(インタフェースと強化類)
http://blog.csdn.net/p_3er/article/details/9239925
b、配置
<!--   Bean -->
	<bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean>
	
	<!-- 
		  
		constructor-arg       
	-->
	<bean id="introductionAdvisor" 
		class="org.springframework.aop.support.DefaultIntroductionAdvisor">
		<constructor-arg>
			<bean class="cn.framelife.spring.advice.IntroductionAdvice"></bean>
		</constructor-arg>
	</bean>	
	
	<!-- 
		     
	-->
	<bean id="incluctionProxy" 
		class="org.springframework.aop.framework.ProxyFactoryBean"
		p:interceptorNames="introductionAdvisor"
		p:target-ref="userDao"
		p:proxyTargetClass="true" />

c、テスト
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		UserDao userDao = (UserDao) context.getBean("aProxy");
		userDao.save();
		
		System.out.println("-------------");
		
		AInterface a = (AInterface)userDao;
		a.say();
		
		System.out.println("-------------");
		userDao.save();

d、結果
       
org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation
save
    ...
       
-------------
       
org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation
say
UserDao   
       
-------------
       
org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation
save
    ...