面向切面的Spring(二) xml中定義aop

z1340954953發表於2018-05-31

Spring的AOP配置元素

 

Spring的AOP配置元素
AOP配置元素 用途
<aop:advisor> 定義AOP通知器
<aop:after> 定義AOP後置通知
<aop:after-returning> 返回通知
<aop:after-throwing> 異常通知
<aop:around> 環繞通知
<aop:aspect> 定義切面
<aop:aspectj-autoproxy> 啟用註解@AspectJ定義的切面
<aop:before> 前置通知
<aop:config> 最頂層的AOP元素,其他<aop:*>必須包含在這個標籤內部
<aop:declare-parents> 為定義的物件引入介面
<aop:pointcut> 定義切點

*切面類,和前面JavaConfig配置不同,將切點定義在xml中

public class Audience {
	public void performance(){}
	public void silencePhones(){
		System.out.println("silence cell phones .... ");
	}
	public void takeState(){
		System.out.println("take state  .... ");
	}
	public void appluase(){
		System.out.println("clap clap clap! ..");
	}
	public void round(ProceedingJoinPoint jp){
		try {
			System.out.println("silence cell phones .... ");
			System.out.println("take state  .... ");
			jp.proceed();
			System.out.println("clap clap clap! ..");
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}
}

* 建立Aspect-xml.xm

 <!-- spring基於註解的配置 -->
   <context:annotation-config/>
   <!-- 掃包自動建立bean -->
   <context:component-scan base-package="com.bing.proxy"></context:component-scan>
   <!-- 建立切面類的bean -->
   <bean id="audience" class="com.bing.proxy.Audience"></bean>
   <aop:config>
   <aop:pointcut expression="execution(* com.bing.proxy.UserService.*(..))" id="usPoint"/>
   	<aop:aspect ref="audience">
   		<aop:before method="silencePhones" pointcut-ref="usPoint"/>
   		<aop:after method="appluase" pointcut-ref="usPoint"/>
   	</aop:aspect>
   </aop:config>

* Junit測試

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value="classpath:aspectJ-xml.xml")
public class CDPlayerTest {
	@Autowired
	private UserService us;
	@Test
	public void test(){
		us.sayAdd();
	}
}

注意到環繞通知,在aop:around元素的method屬性裡寫的也是方法名

* xml中如何為通知傳遞引數

1. 定義切面類

public class TrackCounter {
	private Map<Integer, Integer> trackCounts = new HashMap<Integer, Integer>();
	public void countTrack(int i){
		int currentCount = getPlayCount(i);
		trackCounts.put(i, currentCount+1);
	}
	public int getPlayCount(int count){
		return trackCounts.containsKey(count)?trackCounts.get(count):0;
	}
}

2. 定義連線點

public interface CompactDisc {
	void play();
	void playTrack(int i);
}

每呼叫一次playTrack方法,將方法裡面的引數傳遞到通知中,並記錄

3. xml

 <!-- 建立切面類的bean -->
   <bean id="tc" class="com.bing.proxy.TrackCounter"></bean>
   <!-- 測試bean CompactDisc實現類 -->
   <bean id="sp" class="com.erong.service.SgtPeppers">
   		<constructor-arg index="0" value="十年"></constructor-arg>
   		<constructor-arg index="1" value="陳奕迅"></constructor-arg>
   </bean>
   <aop:config>
	<!-- 給通知傳遞引數 -->   	
   	<aop:aspect ref="tc">
   	<aop:pointcut expression="execution(* com.bing.interface_.CompactDisc.playTrack(int)) and args(i)" id="pt"/>
		<aop:before method="countTrack" pointcut-ref="pt"/>   	
   	</aop:aspect>
   </aop:config>

需要注意的是,AspectJ指示器和前面在JavaConfig中不用的是,&&換成了 and  其他的一致。

* 在xml中向物件引入新的介面

其實就是在定義的物件層次,定義它的父型別。在本例中對UserService的子類增加父型別介面Encoreable。

前面一節,使用@Declareparents實現的。這裡xml中配置如下

<!-- 注入的介面的實現類 -->
	<bean id="de" class="com.erong.service.DefaultEncoreable"></bean>
   <aop:config>
   	<!-- 給現有的物件引入bean -->
   	<aop:aspect>
   		<aop:declare-parents 
   		types-matching="com.bing.proxy.UserService+" 
   		implement-interface="com.bing.interface_.Encoreable"
   		delegate-ref="de"
   		/>
   	</aop:aspect>
   </aop:config>

屬性說明:

* types-matching: 需要引入介面的類

* implement-interface:引入的介面

* delegate-ref:引入的介面預設實現類的Bean

* delegate-impl:引入的介面預設實現類

相關文章