解释就懒得写了,有代码运行一下就知道了,jar除了Spring所必备的以外还要加上bsh-1.2b7.jar
- packagecom.test;
- /**
- *在线图书销售系统业务逻辑接口
- */
- publicinterfaceBookBiz{
- publicfloat[]buy(StringuserName,StringbookName,doubleprice);
- publicvoidcomment(StringuserName,Stringcomments);
- }
- packagecom.test;
- publicclassBookBizImplimplementsBookBiz{
- /**
- *购买图书
- */
- publicfloat[]buy(StringuserName,StringbookName,doubleprice){
- System.out.println("业务方法buy开始执行");
- System.out.println("·"+userName+"购买图书:"+bookName);
- System.out.println("·"+userName+"增加积分:"+(int)(price/10));
- System.out.println("·"+"向物流系统下发货单");
- System.out.println("业务方法buy结束");
- returnnull;
- }
- /**
- *发表书评
- */
- publicvoidcomment(StringuserName,Stringcomments){
- System.out.println("业务方法comment开始执行");
- System.out.println("·"+userName+"发表书评"+comments);
- System.out.println("业务方法comment结束");
- }
- }
- packagecom.test;
- importjava.lang.reflect.Method;
- importjava.util.Arrays;
- importorg.aopalliance.intercept.MethodInterceptor;
- importorg.aopalliance.intercept.MethodInvocation;
- importorg.springframework.aop.AfterReturningAdvice;
- importorg.springframework.aop.MethodBeforeAdvice;
- importbsh.Interpreter;
- publicclassMyAdviceimplementsMethodBeforeAdvice,AfterReturningAdvice,MethodInterceptor{
- /**
- *前通知
- */
- publicvoidbefore(Methodm,Object[]args,Objecttarget)
- throwsThrowable{
- System.out.println("前通知,调用的方法:"+m.getName()+",参数:"+Arrays.toString(args));
- }
- /**
- *后通知
- */
- publicvoidafterReturning(Objectonject,Methodmethod,Object[]args,
- Objectarg3)throwsThrowable{
- System.out.println("后通知,调用的方法:"+method.getName()+",参数:"+Arrays.toString(args));
- }
- /**
- *环绕通知,最维强大的通知,可以控制目标方法是否执行,也可以改变方法的返回值
- */
- publicObjectinvoke(MethodInvocationmethod)throwsThrowable{
- System.out.println("[环绕通知]");
- Object[]args=method.getArguments();
- /**
- *这里我们禁止李四发表任何的评论
- */
- if(method.getMethod().getName().equals("comment")&"李四".equals(args[0])){
- System.out.println("屏蔽李四所有的评论");
- StringreturnType=method.getMethod().getReturnType().getName();
- if("int".equals(returnType)||"long".equals(returnType)||"float".equals(returnType)||"double".equals(returnType)||"byte".equals(returnType)||"short".equals(returnType)){
- //利用BeanShell构造一个内置变量返回,这里想了好久,没有想到什么方法可以根据
- //指定数据类型返回指定的变量
- Interpreteri=newInterpreter();
- returni.eval("("+returnType+")0");
- }elseif("boolean".equals(returnType)){
- returnfalse;
- }
- returnnull;
- }else{
- returnmethod.proceed();
- }
- }
- }
- packagecom.test;
- importorg.springframework.context.ApplicationContext;
- importorg.springframework.context.support.ClassPathXmlApplicationContext;
- publicclassAOPTest{
- /**
- *@paramargs
- */
- publicstaticvoidmain(String[]args){
- ApplicationContextcontext=
- newClassPathXmlApplicationContext("springAop.xml");
- BookBizbookBiz=(BookBiz)context.getBean("bookBiz");
- bookBiz.buy("张三","Spring深入潜出",50);
- bookBiz.comment("李四","《恐怖世界》一点都不恐怖,很好看!");
- bookBiz.comment("张三","《Spring深入潜出》还是写得不错的!");
- }
- }
- <?xmlversion="1.0"encoding="UTF-8"?>
- <!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd">
- <beans>
- <beanid="bookBizTarget"class="com.test.BookBizImpl"/>
- <beanid="myAdvice"class="com.test.MyAdvice"/>
- <beanid="bookBiz"class="org.springframework.aop.framework.ProxyFactoryBean">
- <propertyname="proxyInterfaces">
- <value>com.test.BookBiz</value>
- </property>
- <propertyname="interceptorNames">
- <list>
- <value>myAdvice</value>
- </list>
- </property>
- <propertyname="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深入潜出》还是写得不错的!]
从输出结果可以看出,环绕通知是最先开始执行的,,如果环绕通知把目标方法屏蔽了不执行,那么后面的前后通知都不会执行