Spring中增强:包含横切代码和方位信息 ,增强继承关系如下图:
Advice :其实就是一个增强的标志接口,没有实际的方法需要实现。
前置增强(BeforeAdvice):Spring中只支持方法级别的增强操作,所以MethodBeforeAdvice是目前可用的前置增强,而BeforeAdvice是为了后面扩展。
后置增强(AfterRetruningAdvice) :表示在目标方法执行后实施增强
环绕增强(MethodInterceptor):表示在目标方法执行前后实施增强
异常抛出增强(ThrowsAdvice) 表示在目标方法抛出异常后实施增强
引介增强(IntroductionInterceptor)表示在目标类中添加一些新的方法和属性
1.前置增强案例
增强类代码如下:
/前置增强 public class GreeetingBeforeAdvice implements MethodBeforeAdvice { @Override public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println(this.getClass().getName() + "." + method.getName()); String name = (String) objects[0]; System.out.println("How are you Mr " + name); } }
通过硬编码的方式调用前置增强
public static void textFactoryBean() { //目标类对象 Waiter waiter = new NaviWaiter(); // 前置增强 GreeetingBeforeAdvice greeetingBeforeAdvice = new GreeetingBeforeAdvice(); // 后置增强 GreetingAfterAdvice greetingAfterAdvice = new GreetingAfterAdvice(); // 代理工厂 ProxyFactory factory = new ProxyFactory(); // 设置目标类 factory.setTarget(waiter); // 设置增强 factory.addAdvice(greeetingBeforeAdvice); // 设置后置增强 factory.addAdvice(greetingAfterAdvice); // 获取代理对象 Waiter proxy = (Waiter) factory.getProxy(); proxy.greetTo("zhang"); proxy.serveTo("zhang"); }
通过Spring配置文件来设置 增强数据
<!--设置前置代理-->
代理对象 <bean id="target" class="com.example.AOP.BeforeAdvice.NaviWaiter"/>
//增强Bean <bean id="beforehance" class="com.example.AOP.BeforeAdvice.GreeetingBeforeAdvice"/> <bean id="afterAdvice" class="com.example.AOP.BeforeAdvice.GreetingAfterAdvice"/> <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"//代理工厂Bean 是ProxyFactory的实现类 p:proxyInterfaces="com.example.AOP.BeforeAdvice.Waiter"//代理接口 p:interceptorNames="beforehance,afterAdvice"//织入的增强 p:target-ref="target"
//其中 target表示代理目标类 proxyInterfaces表示代理所要实现的接口,可以是多个接口, interceptorNames:表示需要织入目标对象的Bean列表,
optimize 当设置为True 强制使用CGLib动态代理, proxyTargetClass是否对类进行代理吗,设置为true表示使用CGLib代理
interceptorNames 接收的是Bean的名称而非Bean类 />
NaviWaiter实现Waiter接口后,自己写就行了
2.后置增强案例
后置增强是在目标方法调用完后执行,代码如下:
//后置增强 public class GreetingAfterAdvice implements AfterReturningAdvice { /* 其中 Object object 表示目标方法的返回值 Method method 表示目标方法 objects 表示方法参数 Object o1表示目标类实例 */ @Override public void afterReturning(Object object, Method method, Object[] objects, Object o1) throws Throwable { System.out.println("please enjoy youself"); } }
添加后置增强配置文件如上:
3.环绕增强允许在方法前后加入横切逻辑代码。 Spring使用MethodInterceptor作为环绕增强的接口,
//环绕增强 public class GreetingInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { // 获取目标方法参数 Object[] arguments = invocation.getArguments(); String clientName = (String) arguments[0]; System.out.println("How are you Mr " + clientName + " !"); Object proceed = invocation.proceed(); System.out.println("bye bye " + clientName + " !"); return proceed; } }
环绕增强配置
<!--环绕增强配置--> <bean id="NaviWaiter" class="com.example.AOP.BeforeAdvice.NaviWaiter"/> <bean id="GreetAround" class="com.example.AOP.BeforeAdvice.GreetingInterceptor"/> <bean id="wwwwss" class="org.springframework.aop.framework.ProxyFactoryBean" p:proxyTargetClass="true" p:interceptorNames="GreetAround" p:target-ref="NaviWaiter"/>
4.异常抛出增强 通过实现ThrowsAdvice接口,并设置默认规定方法用于处理异常抛出后的问题。 此接口是一个标签接口,没有任何实际方法,但必须按如下格式处理异常抛出增强方法
void afterThrowing([Method method,Object[] object,Object target],Throwable)此方法的前面三个参数要么都不提供,要么都要提供,Throwable必须提供
5.引介增强案例
//引介增强 public class ControllerPerformaceMonitor extends DelegatingIntroductionInterceptor implements Monitorable { private ThreadLocal<Boolean> local = new ThreadLocal<Boolean>(); @Override public void setMonitorable(boolean active) { local.set(active); } @Override public Object invoke(MethodInvocation mi) throws Throwable { Object object = null; if (local.get() != null && local.get()) { PerFormanceMonitor.begin(mi.getClass().getName() + "." + mi.getMethod().getName()); object = super.invoke(mi); PerFormanceMonitor.end(); } else { object = super.invoke(mi); } return object; }
配置文件
<!--引介增强--> <bean id="Frumservice" class="com.example.AOP.ForumServiceImpl"/> <bean id="yicontro" class="com.example.AOP.introduceAdivice.ControllerPerformaceMonitor"/> <bean id="smtext" class="org.springframework.aop.framework.ProxyFactoryBean" <!--引介增强所要实现的接口--> p:interfaces="com.example.AOP.introduceAdivice.Monitorable" p:target-ref="Frumservice" <!--增强类--> p:interceptorNames="yicontro" <!--必须使用CGLib方式,因为引介增强需要创建子类--> p:proxyTargetClass="true" />