接口
package springMain;
public interface SayHelloInterface {
public void hello();
public void bay();
}
被代理对象
package springMain;
public class Test implements SayHelloInterface {
@Override
public void hello() {
System.out.println("I am Test1");
}
@Override
public void bay() {
System.out.println("bay");
}
}
前置通知代理对象
package before;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class MyMethodBeforeAdvice implements MethodBeforeAdvice{
@Override
//method:被调用方法的名字
//args:给method传递的参数
//target:目标对象
//理解:由于applicationcontext的配置,动态代理对象proxyFactoryBean与要被代理的对象关联了起来
//代理对象proxyFactoryBean把这个前置通知织入到被代理的对象Test1中。然后这个代理对象获取了被代理对象Test1的所有方法
//当调用被代理对象的方法时,动态代理对象就开始调度,先执行前置通知方法,再执行被代理对象爱的方法
//也可以这样理解(就是事实),动态代理对象proxyFactoryBean复制了被代理对象和前置代理的所有方法,并规定,每次执行被代理对象的方法前必须先执行前置代理方法
//请仔细看applicationcontext的配置,动态代理对象里的方法是从接口集里获取的,所以被代理对象的方法必须从接口里重写才能被代理
public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println("前置通知");
}
}
applicationContext.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
default-autowire="no" default-lazy-init="true">
<!-- 配置被代理对象 -->
<bean id="Test" class="springMain.Test"></bean>
<!-- 配置前置通知对象 -->
<bean id="MyMethodBeforeAdvice" class="before.MyMethodBeforeAdvice"></bean>
<!-- 配置后置通知对象 -->
<bean id="MyAfterReturningAdvice" class="after.MyAfterReturningAdvice"></bean>
<!-- 配置环绕通知对象 -->
<bean id="MyMethodAroundAdvice" class="around.MyMethodAroundAdvice"></bean>
<!-- 配置异常通知对象 -->
<bean id="MyThrowsAdvice" class="exception.MyThrowsAdvice"></bean>
<!-- 自定义前置通知的切入点 ,控制哪些方法配置前置通知-->
<!-- 配置代理对象 ,spring提供,按规则配置就可以-->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 配置要被代理的对象,自己灵活定义 -->
<property name="target" ref="Test"/>
<!-- 把通知织入到代理对象 -->
<!-- name不能乱写 -->
<property name="interceptorNames">
<list>
<value>MyMethodBeforeAdvice</value> <!-- 前置通知,相当于把这个前置通知和代理对象关联,也可看作拦截器 -->
<value>MyAfterReturningAdvice</value>
<value>MyMethodAroundAdvice</value>
<value>MyThrowsAdvice</value>
</list>
</property>
<!-- 配置代理接口集 -->
<property name="proxyInterfaces">
<list>
<value>springMain.SayHelloInterface</value>
</list>
</property>
</bean>
</beans>
实现类
package springMain;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
//这里的si是一个动态代理对象,并非SayHelloInterface对象
//如果目标对象实现了接口,则spring使用了jdk的动态代理技术
//如果目标对象实现了接口,则spring使用了CGLIB的动态代理技术
SayHelloInterface si=(SayHelloInterface) ac.getBean("proxyFactoryBean");
si.hello();
System.out.println("----------------");
si.bay();
}
}