解释就懒得写了,有代码运行一下就知道了,jar除了Spring所必备的以外还要加上bsh-1.2b7.jar
- package com.test;
- /**
- * 在线图书销售系统业务逻辑接口
- */
- public interface BookBiz {
- public float[] buy(String userName, String bookName, double price);
- public void comment(String userName, String comments);
- }
- package com.test;
- public class BookBizImpl implements BookBiz {
- /**
- * 购买图书
- */
- public float[] buy(String userName, String bookName, double price) {
- System.out.println("业务方法buy开始执行");
- System.out.println("·"+userName + "购买图书:" + bookName);
- System.out.println("·"+userName + "增加积分:" + (int) (price / 10));
- System.out.println("·"+"向物流系统下发货单");
- System.out.println("业务方法buy结束");
- return null;
- }
- /**
- * 发表书评
- */
- public void comment(String userName, String comments) {
- System.out.println("业务方法comment开始执行");
- System.out.println("·"+userName + "发表书评" + comments);
- System.out.println("业务方法comment结束");
- }
- }
- package com.test;
- import java.lang.reflect.Method;
- import java.util.Arrays;
- import org.aopalliance.intercept.MethodInterceptor;
- import org.aopalliance.intercept.MethodInvocation;
- import org.springframework.aop.AfterReturningAdvice;
- import org.springframework.aop.MethodBeforeAdvice;
- import bsh.Interpreter;
- public class MyAdvice implements MethodBeforeAdvice ,AfterReturningAdvice,MethodInterceptor{
- /**
- * 前通知
- */
- public void before(Method m, Object[] args, Object target)
- throws Throwable {
- System.out.println("前通知,调用的方法:"+m.getName()+",参数:"+Arrays.toString(args));
- }
- /**
- * 后通知
- */
- public void afterReturning(Object onject, Method method, Object[] args,
- Object arg3) throws Throwable {
- System.out.println("后通知,调用的方法:"+method.getName()+",参数:"+Arrays.toString(args));
- }
- /**
- * 环绕通知,最维强大的通知,可以控制目标方法是否执行,也可以改变方法的返回值
- */
- public Object invoke(MethodInvocation method) throws Throwable {
- System.out.println("[环绕通知]");
- Object[] args=method.getArguments();
- /**
- * 这里我们禁止李四发表任何的评论
- */
- if(method.getMethod().getName().equals("comment")&"李四".equals(args[0])){
- System.out.println("屏蔽李四所有的评论");
- String returnType=method.getMethod().getReturnType().getName();
- if("int".equals(returnType)||"long".equals(returnType)||"float".equals(returnType)||"double".equals(returnType)||"byte".equals(returnType)||"short".equals(returnType)){
- //利用BeanShell 构造一个内置变量返回,这里想了好久,没有想到什么方法可以根据
- //指定数据类型 返回指定的变量
- Interpreter i = new Interpreter();
- return i.eval("("+returnType+")0");
- }else if("boolean".equals(returnType)){
- return false;
- }
- return null;
- }else{
- return method.proceed();
- }
- }
- }
- package com.test;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class AOPTest {
- /**
- * @param args
- */
- public static void main(String[] args) {
- ApplicationContext context =
- new ClassPathXmlApplicationContext("springAop.xml");
- BookBiz bookBiz = (BookBiz)context.getBean("bookBiz");
- bookBiz.buy("张三", "Spring深入潜出", 50);
- bookBiz.comment("李四", "《恐怖世界》一点都不恐怖,很好看!");
- bookBiz.comment("张三", "《Spring深入潜出》还是写得不错的!");
- }
- }
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
- <beans>
- <bean id="bookBizTarget" class="com.test.BookBizImpl" />
- <bean id="myAdvice" class="com.test.MyAdvice" />
- <bean id="bookBiz" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="proxyInterfaces">
- <value>com.test.BookBiz</value>
- </property>
- <property name="interceptorNames">
- <list>
- <value>myAdvice</value>
- </list>
- </property>
- <property name="target" ref="bookBizTarget" />
- </bean>
- </beans>
运行AOPTest 这个类,下面是输出结果:
[环绕通知]
前通知,调用的方法:buy,参数:[张三, Spring深入潜出, 50.0]
业务方法buy开始执行
·张三购买图书:Spring深入潜出
·张三增加积分:5
·向物流系统下发货单
业务方法buy结束
后通知,调用的方法:buy,参数:[张三, Spring深入潜出, 50.0]
[环绕通知]
屏蔽李四所有的评论
[环绕通知]
前通知,调用的方法:comment,参数:[张三, 《Spring深入潜出》还是写得不错的!]
业务方法comment开始执行
·张三发表书评《Spring深入潜出》还是写得不错的!
业务方法comment结束
后通知,调用的方法:comment,参数:[张三, 《Spring深入潜出》还是写得不错的!]
从输出结果可以看出,环绕通知是最先开始执行的,,如果环绕通知把目标方法屏蔽了不执行,那么后面的前后通知都不会执行