第4章 面向切面的Spring--xml配置切面 笔记2

概述:

本书建立过这样一种原则,那就是基于注解的配置要优于基于Java的配置,基于Java的配置要优于基于XML的配置。但是,如果你需要声明切面,但是又不能为通知类添加注解的时候,那么就必须转向XML配置了。

基于xml配置切面保证你类看起来很干净

需要用到的标签:

  • <aop:advisor>  定义AOP通知器
  • <aop:after>       定义AOP后置通知(不管被通知的方法是否执行成功)
  • <aop:after-returning>  定义AOP返回通知
  • <aop:after-throwing> 定义AOP异常通知
  • <aop:around> 定义AOP的环绕通知
  • <aop:aspect> 定义一个切面
  • <aop:aspectj-autoproxy> 启用@AspectJ注解驱动的切面
  • <aop:before> 定义一个AOP的前置通知
  • <aop:config>顶层的AOP配置元素,大多数的<aop:*>元素必须包含在<aop:config>元素内
  • <aop:declare-parents> 以透明的方式为被通知的对象引入额外的接口
  • <aop:pointcut> 定义一个切点

首先配置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:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
	<!-- 这里有点dry -->
	<!-- <aop:config>
		<aop:aspect ref="audience">
			<aop:before method="silenceCellPhones"
				pointcut="execution(* *.chapter4.Performance.perform(..))"/>
				
			<aop:before method="takeSeats"
				pointcut="execution(* *.chapter4.Performance.perform(..))"/>
				
			<aop:after-returning method="applause"
				pointcut="execution(* *.chapter4.Performance.perform(..))"/>
				
			<aop:after-throwing method="demandRefund"
				pointcut="execution(* *.chapter4.Performance.perform(..))"/>
		</aop:aspect>
	</aop:config> -->
    <bean id="audience" class="learn.chapter4.Audience"/>
    <bean id="chaplin" class="learn.chapter4.Chaplin"/>
	<aop:config>
		<aop:aspect ref="audience">
			<aop:pointcut expression="execution(* *.chapter4.Performance.perform(..))" 
			id="performance"/>
			<aop:before method="silenceCellPhones"
				pointcut-ref="performance"/>
				
			<aop:before method="takeSeats"
				pointcut-ref="performance"/>
				
			<aop:after-returning method="applause"
				pointcut-ref="performance"/>
				
			<aop:after-throwing method="demandRefund"
				pointcut-ref="performance"/>
		</aop:aspect>
	</aop:config>
</beans>

总结:

1.必须增加aop命名空间

2.注意切点名和bean的Id不能相同 

3.<aop:aspect ref="audience"> 是执行内容 what

package learn.chapter4;

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class Audience {


	public void silenceCellPhones(){
		System.out.println("手机设置成静音状态");
	}
	
	public void takeSeats() {
		System.out.println("选择位子坐下");
	}
	
	public void applause(){
		System.out.println("表演很精彩,鼓掌!");
	}
	
	public void demandRefund(){
		System.out.println("太烂了,请求退款");
	}
	
}
package learn.chapter4;

public class Chaplin implements Performance{

	public void perform() {
		System.out.println("卓别林正在表演哑剧。。。。。");
	}

}


package learn.chapter4.javaConfig;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

@Configuration
@ImportResource("classpath:aop.xml")
public class XmlConfig {

}
总结:通过@ImportResource导入xml配置文件

package learn.chapter4;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import learn.chapter4.javaConfig.XmlConfig;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={XmlConfig.class})
public class XmlAOPTest {

	@Autowired
	private Performance performance;
	
	@Test
	public void play(){
		performance.perform();
	}
	
}

结果为:

手机设置成静音状态
选择位子坐下
卓别林正在表演哑剧。。。。。
表演很精彩,鼓掌!

环绕通知:(将上面4个合并为一个环绕通知)

package learn.chapter4;

import org.aspectj.lang.ProceedingJoinPoint;

public class Audience {

	public void watchPerformance(ProceedingJoinPoint jp){
		try{
			System.out.println("手机设置成静音状态");
			System.out.println("选择位子坐下");
			jp.proceed();
			System.out.println("表演很精彩,鼓掌!");
		} catch (Throwable e) {
			System.out.println("太烂了,请求退款");
		}
	}
	
}

然后修改一个配置

<aop:config>
<aop:aspect ref="audience">
<aop:pointcut expression="execution(* *.chapter4.Performance.perform(..))" 
id="performance"/>
< aop:around method=" watchPerformance"
pointcut-ref="performance"/>
</aop:aspect>
</aop:config>

2。为通知传递参数

创建一个计数的类

package learn.chapter4;

import java.util.HashMap;
import java.util.Map;

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

public class TrackCounter {

	private Map<Integer, Integer> trackCounts = 
			new HashMap<Integer, Integer>();
	

	public void trackPlayed(int trackNumber){}
	
	public void countTrack(int trackNumber) {
		System.out.println("===================");
		int currentCount = getPlayCount(trackNumber);
		trackCounts.put(trackNumber, currentCount+1);
	}

	public int getPlayCount(int trackNumber) {
		return trackCounts.containsKey(trackNumber) 
				? trackCounts.get(trackNumber) : 0;
	}
	
	
}
增加 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:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
	<bean id="trackCounter" class="learn.chapter4.TrackCounter"/>
	<bean id="cd" class="learn.chapter4.BlankDisc">
		<property name="title" value="beyond"/>
		<property name="artist" value="25年精选"/>
		<property name="tracks">
			<list>
				<value>海阔天空</value>
				<value>光辉岁月</value>
				<value>情人</value>
				<value>谁伴我闯荡</value>
				<value>不再犹豫</value>
				<value>冷雨夜</value>
			</list>
		</property>
	</bean>
	<aop:config>
		<aop:aspect ref="trackCounter">
			<aop:pointcut expression="execution(* *.chapter4.CompactDisc.playTrack(int)) 
				and args(trackNumber)"
			 id="trackPlayed"/>
			 <aop:before method="countTrack"
			 	pointcut-ref="trackPlayed"/>
		</aop:aspect>
	</aop:config>
</beans>

测试类:

package learn.chapter4;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import learn.chapter4.javaConfig.XmlConfig;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={XmlConfig.class})
public class TrackCounterTest {

	@Autowired
	private CompactDisc cd;
	@Autowired
	private TrackCounter counter;
	
	@Test
	public void testCounter(){
		cd.playTrack(0);
		cd.playTrack(1);
		cd.playTrack(2);
		cd.playTrack(3);
		cd.playTrack(3);
		cd.playTrack(4);
		cd.playTrack(5);
		cd.playTrack(5);
		cd.playTrack(5);
		
		System.out.println(counter.getPlayCount(1));
		System.out.println(counter.getPlayCount(2));
		System.out.println(counter.getPlayCount(3));
		System.out.println(counter.getPlayCount(4));
		System.out.println(counter.getPlayCount(5));
		System.out.println(counter.getPlayCount(0));
	}
	
}
package learn.chapter4;

/**
 * 定义一个CD接口
 * @author chenliang
 *
 */
public interface CompactDisc {
	void play();
	void playTrack(int num);
}

package learn.chapter4;

import java.util.List;

public class BlankDisc implements CompactDisc {

	private String title;
	
	private String artist;
	
	private List<String> tracks;
	
	public BlankDisc() {
		super();
		// TODO Auto-generated constructor stub
	}

	public BlankDisc(String title, String artist) {
		super();
		this.title = title;
		this.artist = artist;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getArtist() {
		return artist;
	}

	public void setArtist(String artist) {
		this.artist = artist;
	}

	public List<String> getTracks() {
		return tracks;
	}

	public void setTracks(List<String> tracks) {
		this.tracks = tracks;
	}
	

	@Override
	public String toString() {
		return "BlankDisc [title=" + title + ", artist=" + artist + ", tracks=" + tracks + "]";
	}

	public void play() {
		System.out.println("专辑为" + title + "\t 歌手为:" + artist);
		if(null!=tracks && tracks.size() > 0){
			for (String track : tracks){
				System.out.println("---磁道: " + track);
			}
		}
	}

	public void playTrack(int num) {
		System.out.println("获取对应磁道:" + num +"\t 歌曲为:"+ tracks.get(num));
		
	}
}


结果:

===================
获取对应磁道:0 歌曲为:海阔天空
===================
获取对应磁道:1 歌曲为:光辉岁月
===================
获取对应磁道:2 歌曲为:情人
===================
获取对应磁道:3 歌曲为:谁伴我闯荡
===================
获取对应磁道:3 歌曲为:谁伴我闯荡
===================
获取对应磁道:4 歌曲为:不再犹豫
===================
获取对应磁道:5 歌曲为:冷雨夜
===================
获取对应磁道:5 歌曲为:冷雨夜
===================
获取对应磁道:5 歌曲为:冷雨夜
1
1
2
1
3
1
总结:xml配置AOP比较简洁,适用范围广

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值