1、通知的分类
<1>环绕通知(方法的拦截):MethodInterceptor
<2>前置通知:
实现步骤:
①.通知类实现MethodBeforeAdvice接口
②.重写方法before()
③.配置前置通知类
④.拦截器添加
<property name="interceptorNames">
<list>
<idref bean="前置通知id">
<idref bean="环绕通知id">
</list>
</property>
<3>后置通知:
实现步骤:
①.通知类实现AfterReturningAdvice接口
②.重写方法afterReturning
③.配置后置通知类
④.拦截器添加
<property name="interceptorNames">
<list>
<idref bean="后置通知id">
<idref bean="环绕通知id">
</list>
</property>
注意:配置通知顺序
前置通知--->后置通知--->环绕通知
2、过滤通知
步骤:
①.配置:通知过滤条件
<bean id="通知过滤id" class="RegexpMethodPointcutAdvisor类全限定名">
<property name="advice" ref="通知分类id"></property>
<property name="pattern">
<value>.*匹配字符串.*</value><!-- 配置不过滤的方法 这里方法名可只写前几个字母 -->
</property>
</bean>
我在这里举一个Spring实现AOP的例子
首先第一步:写一个interface
package com.zking.entitySpring;
/**
* Spring代理:艺人
* @author Administrator
*
*/
public interface Artor {
public void show();
public void playDD();
}
第二步:写一个明星类
package com.zking.entitySpring;
/**
* (明星:杨幂)目标:Target
* @author Administrator
*
*/
public class Yangmi implements Artor{
public void show() {
System.out.println("杨幂(~^_^~)");
}
public void playDD() {
System.out.println("杨幂正在打豆豆");
}
}
第三步:写一个经纪人的类
package com.zking.entitySpring;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
* (覃西经纪人)通知advice 环绕通知
* @author Administrator
*
*/
public class QinXi implements MethodInterceptor{
public Object invoke(MethodInvocation invocation) throws Throwable {
Object o=invocation.proceed();//本质代表show()方法
return o;
}
}
第四步:写一个前置和一个后置的类
package com.zking.entitySpring;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
/**
* 前置通知
* @author Administrator
*
*/
public class QH implements MethodBeforeAdvice{
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
System.out.println("前置经纪人");
}
}
package com.zking.entitySpring;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
/**
* 后置通知
* @author Administrator
*
*/
public class HH implements AfterReturningAdvice{
public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
System.out.println("后置经纪人");
}
}
第五步写一个配置xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置目标target 《明星=杨幂=原对象》-->
<bean id="yangmi" class="com.zking.entitySpring.Yangmi"></bean>
<!-- 配置通知:前置通知 -->
<bean id="qh" class="com.zking.entitySpring.QH"></bean>
<!-- 配置通知 advice 《经纪人=覃西=通知》-->
<bean id="qinxi" class="com.zking.entitySpring.QinXi"></bean>
<!-- 配置通知:后置通知 -->
<bean id="hh" class="com.zking.entitySpring.HH"></bean>
<!-- 配置前置通知的过滤通知 -->
<bean id="myBefore" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="qh"></property>
<property name="pattern" value=".*play.*"></property>
</bean>
<!-- 配置后置通知的过滤通知 -->
<bean id="myAfter" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="hh"></property>
<property name="pattern" value=".*play.*"></property>
</bean>
<!-- 配置混合代理对象 -->
<bean id="myProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 1.引用目标(target)对象(原对象) -->
<property name="target" ref="yangmi"></property>
<!-- 2.目标对象实现的所有接口 (proxyInterfaces多个接口)-->
<property name="proxyInterfaces">
<list>
<!-- 接口的全限定名 -->
<value>com.zking.entitySpring.Artor</value>
</list>
</property>
<!-- 3.引用通知:用两种调用的方法 -->
<property name="interceptorNames">
<list>
<!-- 第一种 注意:配置通知顺序 :前置通知>后置通知>环绕通知-->
<!-- 1.前置通知 -->
<idref bean="myBefore"/>
<!-- 2.后置通知 -->
<idref bean="myAfter"/>
<!-- 3.环绕通知 -->
<idref bean="qinxi"/>
<!-- 第二种 -->
<!-- <value>qinxi</value> -->
</list>
</property>
</bean>
</beans>
最后:测试
package com.zking.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.zking.entitySpring.Artor;
public class TestPerson {
@Test
public void test(){
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
Artor artor=(Artor) ac.getBean("myProxy");
artor.playDD();
}
}
测试结果
如果调用的playDD()方法,测试就会打印前置和后置
如果打印的是show()方法,测试就不会打印前置和后置