在Spring的面向切面(AOP)中有五大通知(advice),分别为前置通知,后置通知,环绕通知以及异常通知:
前置通知:在目标方法前执行的通知,实现MenthodBeforeAdvice接口
后置通知:在目标方法执行之后,无论是否发生异常,都进行执行的通知,实现AfterReturningAdvice接口
异常通知:在目标方法出现异常时才会进行执行的代码,实现ThrowsAdvice接口
环绕通知:环绕通知是所有通知类型中功能最为强大的,能够全面地控制连接点,实现MethodInterceptor接口。甚至可以控制是否执行连接点。类似于动态代理。环绕通知 连接点的参数类型必须是 ProceedingJoinPoint ,它是 JoinPoint 的子接口,允许控制何时执行, 是否执行连接点。环绕通知中需要明确调用 ProceedingJoinPoint 的 proceed() 方法来执行被代理的方法,如果忘记这样做就会导致通知被执行了,但目标方法没有被执行。环绕通知的方法需要有返回值,返回目标方法执行之后的结果,即调用 joinPoint.proceed() 的返回值, 否则会出现空指针异常
实例如下:
首先定义一个接口IPerson:
package com.zking.proxy3;
public interface IPersosn {
public void work();
}
具体实现类JackSon:
package com.zking.proxy3;
public class JackSon implements IPersosn{
@Override
public void work() {
// TODO Auto-generated method stub
System.out.println("拜托了!冰箱");
}
}
前置通知实现类:
package com.zking.proxy3;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class MyBefore implements MethodBeforeAdvice{
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
// TODO Auto-generated method stub
System.out.println("前置通知!!!");
}
}
后置通知实现类:
package com.zking.proxy3;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class MyAfter implements AfterReturningAdvice{
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
// TODO Auto-generated method stub
System.out.println("后置通知!!!");
}
}
环绕通知实现类:
package com.zking.proxy3;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class MyInterceptor implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// TODO Auto-generated method stub
System.out.println("环绕通知!!!");
return invocation.proceed();
}
}
异常通知实现类:
package com.zking.proxy3;
import java.lang.reflect.Method;
import org.springframework.aop.ThrowsAdvice;
public class MyThrows implements ThrowsAdvice {
public void afterThrowing(Method m, Object[] os, Object target, Exception e) {
System.out.println("出异常了..." + e.getMessage());
}
}
Spring配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
<!-- 配置目标 -->
<bean id="jackson" class="com.zking.proxy3.JackSon"></bean>
<!-- 配置前置通知 -->
<bean id="MyBefore" class="com.zking.proxy3.MyBefore"></bean>
<bean id="MyAfter" class="com.zking.proxy3.MyAfter"></bean>
<bean id="MyInterceptor" class="com.zking.proxy3.MyInterceptor"></bean>
<bean id="MyThrows" class="com.zking.proxy3.MyThrows"></bean>
<!-- 配置一个混合代理对象 -->
<bean id="myProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 引入目标 -->
<property name="target" ref="jackson"></property>
<!-- 代理类的接口 -->
<property name="proxyInterfaces">
<list>
<value>com.zking.proxy3.IPersosn</value>
</list>
</property>
<!-- 引入通知 -->
<property name="interceptorNames">
<list>
<idref bean="MyBefore"/>
<idref bean="MyAfter"/>
<idref bean="MyInterceptor"/>
<idref bean="MyThrows"/>
</list>
</property>
</bean>
</beans>
测试类:
package com.zking.temp;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.zking.proxy3.IPersosn;
public class Temp {
@Test
public void SpringBean() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
IPersosn ip=(IPersosn) applicationContext.getBean("myProxy");
ip.work();
}
}
结果如下: