Spring3.0 入门进阶(三):基于XML方式的AOP使用

AOP是一个比较通用的概念,主要关注的内容用一句话来说就是"如何使用一个对象代理另外一个对象",不同的框架会有不同的实现,Aspectj 是在编译期就绑定了代理对象与被代理对象的关系,而Spring是在运行期间通过动态代理的方式来现实代理对象与被代理对象的绑定.具体的概念可以参考各自的文档:

Spring: http://docs.spring.io/spring/docs/3.2.1.RELEASE/spring-framework-reference/html/aop.html#aop-introduction

Aspecctj:http://eclipse.org/aspectj/


接下来仍然通过一个综合的例子来说明使用XML的方式如何使用Spring AOP

入口类

package com.eric.introduce;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.eric.introduce.aop.Contestant;
import com.eric.introduce.aop.IUser;
import com.eric.introduce.aop.Worker;
import com.eric.introduce.di.Performer;

public class AOPCaller {

	private static final String CONFIG = "com/eric/introduce/aop/aop.xml";
	private static ApplicationContext context = new ClassPathXmlApplicationContext(
			CONFIG);

	public static void main(String[] args) {
		// simpleAOPCase();
		// arguementAOPTest();
		demoDeclareParents();
	}

	/**
	 * 演示了aop after-returning/before/after-throwing/around
	 * NOTE:如果在performer()方法执行的过程中产生异常且在around的方法中捕获了异常
	 * ,则after-throwing对应的方法不会被执行
	 */
	public static void simpleAOPCase() {
		// 必须是接口类型,否则会包ClassCastException
		Performer eric = (Performer) context.getBean("performer1");
		eric.performer();
	}

	/**
	 * 演示:aop 参数的传递方法
	 * 在用户开户成功后,发送一条问候短信,通过userName参数把用户名发给SMSGreeting
	 */
	public static void arguementAOPTest() {
		IUser user = (IUser) context.getBean("user");
		user.openAccount("Eric");
	}

	/**
	 * 演示aop:declare-parents 的用法
	 * 在不改变源码的情况下,让Worker的子类包含Contestant接口的功能.
	 * getBean("worker")返回的对象即可以强转成Worker也可以强转成Contestant,而该对象只是实现了Worker接口
	 */
	public static void demoDeclareParents() {
		Worker worker = (Worker) context.getBean("worker");
		worker.hardWord();
		((Contestant) worker).receiveAward();

		Contestant worker2 = (Contestant) context.getBean("worker");
		worker2.receiveAward();
		((Worker) worker2).hardWord();
	}

}

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: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/aop 
	http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

	<bean id="audience" class="com.eric.introduce.aop.Audience" />
	<bean id="performer1" class="com.eric.introduce.di.InstrumentPerformer" />

	<bean id="user" class="com.eric.introduce.aop.MobileUser" />
	<bean id="smsgreeting" class="com.eric.introduce.aop.SMSGreeting" />
	<!-- 为了使用aop:declare-parents特性,ITWorker必须声明为Worker接口的子类 -->
	<bean id="worker" class="com.eric.introduce.aop.ITWorker" />


	<aop:config>
		<aop:aspect ref="audience">
			<aop:pointcut
				expression="execution(* com.eric.introduce.di.InstrumentPerformer.performer(..))"
				id="performance" />
			<aop:before method="takeSeat" pointcut-ref="performance" />
			<aop:before method="turnOffCell" pointcut-ref="performance" />
			<aop:after-returning method="applaud"
				pointcut-ref="performance" />
			<aop:after-throwing method="demandRefund"
				pointcut-ref="performance" />

			<aop:around method="calculateTime" pointcut-ref="performance" />
		</aop:aspect>

		<aop:aspect ref="smsgreeting">
			<aop:pointcut
				expression="execution(* com.eric.introduce.aop.MobileUser.openAccount(String)) and args(userName)"
				id="openaccount" />
			<!-- 在用户开户成功后,发送一条问候短信,通过userName参数把用户名发给SMSGreeting -->
			<aop:after-returning method="greeting"
				pointcut-ref="openaccount" arg-names="userName" />

		</aop:aspect>

		<aop:aspect>
			<!-- 在不改变源码的情况下,让Worker的子类包含Contestant接口的功能 -->
			<!-- com.eric.introduce.aop.Worker+ 说明针对Worker的子类有效 -->
			<aop:declare-parents types-matching="com.eric.introduce.aop.Worker+"
				implement-interface="com.eric.introduce.aop.Contestant"
				default-impl="com.eric.introduce.aop.GraciousContestant" />
		</aop:aspect>

	</aop:config>

</beans>

其他相关类

after-returning/before/after-throwing/around 相关

package com.eric.introduce.aop;

import org.aspectj.lang.ProceedingJoinPoint;

/**
 * 观众类
 * 
 * @author Eric
 * 
 */
public class Audience {
	public void takeSeat() {
		System.out.println("AOP: Enter, take seat");
	}

	public void turnOffCell() {
		System.out.println("AOP: Show will start, turn off cell");
	}

	public void applaud() {
		System.out.println("AOP: Nice performance, applaud");
	}

	public void demandRefund() {
		System.out.println("AOP: Bad Performance, Return money");
	}

	public void calculateTime(ProceedingJoinPoint joinPoint) {
		long begintime = System.currentTimeMillis();
		try {
			joinPoint.proceed();
		} catch (Throwable exception) {
			System.out.println("Live Show has Exception");
		}

		long end = System.currentTimeMillis();
		System.out.println("AOP aRound: Spent Time:" + (end - begintime));
	}

}

package com.eric.introduce.di;

import java.util.List;
import java.util.Properties;

/**
* 定义一个表演者,这个表演者实现Performer接口
* 
* @author Eric
* 
*/
public class InstrumentPerformer implements Performer {

 /**
  * demo injection value
  */
 private String name;
 /**
  * demo injection Ref Bean
  */
 private Instrument instrument;

 /**
  * demo injection original typ
  */
 private int age;

 /**
  * demo injection internal bean
  */
 private Instrument privateInstrument;
 /**
  * demo injection List/Set/Array
  */
 private List<Fruit> favFruit;

 /**
  * demo injection Properties/Map
  */
 private Properties properties;

 @Override
 public void performer() {
  System.out.println("Normal Instrument:");
  try {
   Thread.sleep(1999);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  instrument.play();
  System.out.println("Special Instrument:");
  privateInstrument.play();
 }

 @Override
 public void eatFruit() {
  for (Fruit fruit : favFruit) {
   fruit.eat();
  }
 }

 @Override
 public void printProperties() {
  System.out.println(name + " Properties:\n");
  for (Object key : properties.keySet()) {
   System.out.println(key + " " + properties.getProperty((String) key)
     + " \n");
  }
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public Instrument getInstrument() {
  return instrument;
 }

 public void setInstrument(Instrument instrument) {
  this.instrument = instrument;
 }

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }

 public Instrument getPrivateInstrument() {
  return privateInstrument;
 }

 public void setPrivateInstrument(Instrument privateInstrument) {
  this.privateInstrument = privateInstrument;
 }

 public List<Fruit> getFavFruit() {
  return favFruit;
 }

 public void setFavFruit(List<Fruit> favFruit) {
  this.favFruit = favFruit;
 }

 public Properties getProperties() {
  return properties;
 }

 public void setProperties(Properties properties) {
  this.properties = properties;
 }

}

aop:declare-parents 相关

package com.eric.introduce.aop;

/**
 * 主要用来演示declare-parents
 * 
 * @author Eric
 * 
 */
public interface Contestant {
	public void receiveAward();
}

package com.eric.introduce.aop;

public class GraciousContestant implements Contestant {

	@Override
	public void receiveAward() {
		System.out.println("receiveAward was executed");
	}

}

package com.eric.introduce.aop;

public class ITWorker implements Worker {
	public void hardWord() {
		System.out.println("Worker is working hard!");
	}
}


package com.eric.introduce.aop;

/**
 * 主要用来演示declare-parents
 * 
 * @author Eric
 * 
 */
public interface Worker {
	public void hardWord();
}

参数相关

package com.eric.introduce.aop;

/**
 * 定义一个问候接口
 * @author Eric
 * 
 */
public interface IGreeting {
	/**
	 * 定义了问候方法,但检测到有用户开户时,通过AOP机制自动发送问候短信
	 * @param name
	 */
	public void greeting(String name);
}


package com.eric.introduce.aop;

public interface IUser {
	/**
	 * 开户操作
	 * @param name
	 */
	public void openAccount(String name);
}


package com.eric.introduce.aop;

public class MobileUser implements IUser {

	@Override
	public void openAccount(String name) {
		System.out.println("Register Succssful:" + name);
	}

}


package com.eric.introduce.aop;

/**
 * 短信問候
 * @author Eric
 *
 */
public class SMSGreeting implements IGreeting {

	@Override
	public void greeting(String name) {
		System.out.println("Dear " + name + " Welcome to use CMCC");
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值