Spring AOP 示例

本文通过一个在线图书销售系统的案例,展示了如何使用Spring AOP实现方法调用前后的通知、环绕通知等功能,并通过具体代码演示了如何阻止特定用户发表评论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

解释就懒得写了,有代码运行一下就知道了,jar除了Spring所必备的以外还要加上bsh-1.2b7.jar

  1. package com.test;
  2. /**
  3.  * 在线图书销售系统业务逻辑接口
  4.  */
  5. public interface BookBiz {
  6.     public float[] buy(String userName, String bookName, double price);
  7.     public void comment(String userName, String comments);
  8. }

 

  1. package com.test;
  2. public class BookBizImpl implements BookBiz {
  3.     /**
  4.      * 购买图书
  5.      */
  6.     public float[] buy(String userName, String bookName, double price) {
  7.         System.out.println("业务方法buy开始执行");
  8.         System.out.println("·"+userName + "购买图书:" + bookName);
  9.         System.out.println("·"+userName + "增加积分:" + (int) (price / 10));
  10.         System.out.println("·"+"向物流系统下发货单");
  11.         System.out.println("业务方法buy结束");
  12.         return null;
  13.     }
  14.     /**
  15.      * 发表书评
  16.      */
  17.     public void comment(String userName, String comments) {
  18.         System.out.println("业务方法comment开始执行");
  19.         System.out.println("·"+userName + "发表书评" + comments);
  20.         System.out.println("业务方法comment结束");
  21.     }
  22. }
  1. package com.test;
  2. import java.lang.reflect.Method;
  3. import java.util.Arrays;
  4. import org.aopalliance.intercept.MethodInterceptor;
  5. import org.aopalliance.intercept.MethodInvocation;
  6. import org.springframework.aop.AfterReturningAdvice;
  7. import org.springframework.aop.MethodBeforeAdvice;
  8. import bsh.Interpreter;
  9. public class MyAdvice implements MethodBeforeAdvice ,AfterReturningAdvice,MethodInterceptor{
  10.     /**
  11.      * 前通知
  12.      */
  13.     public void before(Method m, Object[] args, Object target)
  14.         throws Throwable {
  15.         System.out.println("前通知,调用的方法:"+m.getName()+",参数:"+Arrays.toString(args));
  16.     }
  17.     /**
  18.      * 后通知
  19.      */
  20.     public void afterReturning(Object onject, Method method, Object[] args,
  21.             Object arg3) throws Throwable {
  22.         System.out.println("后通知,调用的方法:"+method.getName()+",参数:"+Arrays.toString(args));
  23.     }
  24.     /**
  25.      * 环绕通知,最维强大的通知,可以控制目标方法是否执行,也可以改变方法的返回值
  26.      */
  27.     public Object invoke(MethodInvocation method) throws Throwable {
  28.         System.out.println("[环绕通知]");
  29.         Object[] args=method.getArguments();
  30.         /**
  31.          * 这里我们禁止李四发表任何的评论
  32.          */
  33.         if(method.getMethod().getName().equals("comment")&"李四".equals(args[0])){
  34.             System.out.println("屏蔽李四所有的评论");
  35.             String returnType=method.getMethod().getReturnType().getName();
  36.             if("int".equals(returnType)||"long".equals(returnType)||"float".equals(returnType)||"double".equals(returnType)||"byte".equals(returnType)||"short".equals(returnType)){
  37.                 //利用BeanShell 构造一个内置变量返回,这里想了好久,没有想到什么方法可以根据
  38.                 //指定数据类型 返回指定的变量
  39.                 Interpreter i = new Interpreter();
  40.                 return i.eval("("+returnType+")0");
  41.             }else if("boolean".equals(returnType)){
  42.                 return false;
  43.             }
  44.             return null;
  45.         }else{
  46.             return method.proceed();
  47.         }
  48.     }   
  49. }
  1. package com.test;
  2. import org.springframework.context.ApplicationContext;
  3. import org.springframework.context.support.ClassPathXmlApplicationContext;
  4. public class AOPTest {
  5.     /**
  6.      * @param args
  7.      */
  8.     public static void main(String[] args) {
  9.         ApplicationContext context = 
  10.             new ClassPathXmlApplicationContext("springAop.xml");
  11.         BookBiz bookBiz = (BookBiz)context.getBean("bookBiz");
  12.         bookBiz.buy("张三""Spring深入潜出", 50);
  13.         bookBiz.comment("李四""《恐怖世界》一点都不恐怖,很好看!");
  14.         bookBiz.comment("张三""《Spring深入潜出》还是写得不错的!");
  15.     }
  16. }
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
  3. <beans>
  4.     <bean id="bookBizTarget" class="com.test.BookBizImpl" />
  5.     <bean id="myAdvice" class="com.test.MyAdvice" />
  6.     <bean id="bookBiz" class="org.springframework.aop.framework.ProxyFactoryBean">
  7.         <property name="proxyInterfaces">
  8.             <value>com.test.BookBiz</value>
  9.         </property>
  10.         <property name="interceptorNames">
  11.             <list>
  12.             <value>myAdvice</value>
  13.             </list>
  14.         </property>
  15.         <property name="target" ref="bookBizTarget" />
  16.     </bean>
  17. </beans>

运行AOPTest 这个类,下面是输出结果:

 

 

[环绕通知]
前通知,调用的方法:buy,参数:[张三, Spring深入潜出, 50.0]
业务方法buy开始执行
·张三购买图书:Spring深入潜出
·张三增加积分:5
·向物流系统下发货单
业务方法buy结束
后通知,调用的方法:buy,参数:[张三, Spring深入潜出, 50.0]
[环绕通知]
屏蔽李四所有的评论
[环绕通知]
前通知,调用的方法:comment,参数:[张三, 《Spring深入潜出》还是写得不错的!]
业务方法comment开始执行
·张三发表书评《Spring深入潜出》还是写得不错的!
业务方法comment结束
后通知,调用的方法:comment,参数:[张三, 《Spring深入潜出》还是写得不错的!]

 

从输出结果可以看出,环绕通知是最先开始执行的,,如果环绕通知把目标方法屏蔽了不执行,那么后面的前后通知都不会执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值