代理模式实现前置通知、后置通知和环绕通知。
代理目标接口:
package com.print;
public interface IPrinter {
public String print(String content);
}
代理目标类:
package com.print.impl;
import com.print.IPrinter;
public class Printer implements IPrinter {
public String print(String content) {
System.out.println(输出内容:["+content+"]");
return content;
}
}
- 前置通知:
切面类:
package com.print.advices;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class MyBeforAdvice implements MethodBeforeAdvice {
/**
* @param m 被通知的方法对象,args 被通知的方法的参数,taget 被代理的没标类对象
*/
public void before(Method m, Object[] args, Object taget)
throws Throwable {
System.out.println("前置通知开始:--------------");
System.out.println("方法名:"+m.getName());
System.out.println("参数列表长度:"+args.length);
System.out.println("参数:");
for(Object a : args){
System.out.println("\t"+a.toString());
}
System.out.println("对象名:"+taget.getClass().getName());
System.out.println("前置通知结束-----------------");
}
}
Spring配置:
<!--前置通知切面bean -->
<bean id="beforAdvice" class="com.etp.zsh.MyBeforeAdvice"/>
<!-- 代理目标bean -->
<bean id="taget" class="com.print.impl.Printer"/>
<!-- 代理bean -->
<bean id="printer" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 注入属性代理目标接口 -->
<property name="proxyInterfaces" value="com.print.IPrinter "/>
<!-- 注入属性代理目标bean -->
<property name="target" ref="taget"/>
<!-- 注入属性切面bean -->
<property name="interceptorNames">
<list>
<value>beforAdvice</value>
</list>
</property>
</bean>
测试类:
package com.print.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.print.IPrinter;
public class Test {
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext("/src/applicationContext.xml");
IPrinter colorPrinter = (IPrinter)context.getBean("printer");
colorPrinter.print("do something");
}
}
输出结果:
前置通知开始:--------------
方法名:print
参数列表长度:1
参数:
do something
对象名:com.print.impl.Printer
前置通知结束----------------
输出内容:[do something]
- 后置通知:
依然使用上边的目标类
后置通知切面类:
package com.print.advices;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class MyAfterReturnAdvice implements AfterReturningAdvice {
/**
* @param returnObj 被通知方法的返回值, m 被通知的方法对象,args 被通知的方法的参数,taget 被代理的没标类对象
*/
public void afterReturning(Object returnObj, Method m, Object[] args,
Object taget) throws Throwable {
System.out.println("后置通知开始:--------------");
System.out.println("方法返回值:"+ returnObj);
System.out.println("方法名:"+m.getName());
System.out.println("参数列表长度:"+args.length);
System.out.println("参数:");
for(Object a : args){
System.out.println("\t"+a.toString());
}
System.out.println("对象名:"+taget.getClass().getName());
System.out.println("后置通知结束----------------");
}
}
在applicationContext.xml中添加后置通知切面bean配置:
<!-- 后置通知切面 -->
<bean id="arterReturnAdvice" class="com.print.advices.MyAfterReturnAdvice"/>
在代理bean中添加切面arterReturnAdvice:
<property name="interceptorNames">
<list>
<value>beforAdvice</value>
<value>arterReturnAdvice</value>
</list>
</property>
运行测试,得到结果:
前置通知开始:--------------
方法名:print
参数列表长度:1
参数:
do something
对象名:com.print.impl.Printer
前置通知结束----------------
输出内容:[do something]
后置通知开始:--------------
方法返回值:do something
方法名:print
参数列表长度:1
参数:
do something
对象名:com.print.impl.Printer
后置通知结束----------------
三、环绕通知:
依然使用上边的目标类
环绕通知切面类:
package com.print.advices;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class MyInterceptor implements MethodInterceptor {
/**
* @param invocation 被代理的目标对象
*/
public Object invoke(MethodInvocation invocation) throws Throwable {
Object returnObj = null;
System.out.println("{{{{{{环绕通知开始}}}}}}");
//执行代理目标的被通知的方法
returnObj = invocation.proceed();
System.out.println("{{{{{{环绕通知结束}}}}}}");
return returnObj;
}
}
在applicationContext.xml中添加环绕通知切面bean配置:
<!-- 环绕通知切面 -->
<bean id="myInterceptor" class="com.print.advices.MyInterceptor"/>
在代理bean中添加切面myInterceptor:
<property name="interceptorNames">
<list>
<value>beforAdvice</value>
<value>arterReturnAdvice</value>
<value>myInterceptor</value>
</list>
</property>
运行测试,得到结果:
前置通知开始:--------------
方法名:print
参数列表长度:1
参数:
do something
对象名:com.print.impl.Printer
前置通知结束----------------
{{{{{{环绕通知开始}}}}}}
输出内容:[do something]
{{{{{{环绕通知结束}}}}}}
后置通知开始:--------------
方法返回值:do something
方法名:print
参数列表长度:1
参数:
do something
对象名:com.print.impl.Printer
后置通知结束----------------