spring aop 的主要原理就是动态代理。
代理模式(proxy):动态代理(JDk/cglib)和静态代理
动态代理必须实现InvocationHandler接口,实现invoke()方法;
start......
test......测试数据
end......
因此,我们就可以把上面代码的
System.out.println("start...... ") 替换成things.wear()(利用IOC的反射原理),
System.out.println("end......")替换成things.working()(利用IOC的反射原理).
代理模式(proxy):动态代理(JDk/cglib)和静态代理
JDk与CGLib动态代理区别:如果目标对象是接口,那么适合使用JDK来生成代理,负责spring会使用CGLIB来生成代理。
JDk动态代理:动态代理必须实现InvocationHandler接口,实现invoke()方法;
invoke()方法有3个参数:分别代表代理的真实对象、调用的对象的方法的Method对象、方法的参数
例子:
IPerson.java:
public interface IPerson {
void test(String test);
}
Person.java:
public class Person implements IPerson{
@Override
public void test(String test) {
System.out.println("test......"+test);
}
}
PersonProxy.java 实现InvocationHandler接口:
public class PersonProxy implements InvocationHandler {
//目标对象
private IPerson person;
public PersonProxy(IPerson person){
this.person = person;
}
public IPerson getProxy(){
Class<?>[] interfaces = new Class[]{IPerson.class};
//newProxyInstance在jvm运行时动态生成的对象
//参数分别是:类加载对象、interface数组、InvocationHandler对象
return (IPerson) Proxy.newProxyInstance(IPerson.class.getClassLoader(),
interfaces,this);
}
@Override
public Object invoke(Object target, Method method, Object[] params)
throws Throwable {
//Person.test()执行前添加自己的操作
System.out.println("start...... ");
Object obj = method.invoke(person, params);
//Person.test()执行后添加自己的操作
System.out.println("end......");
return obj;
}
}
测试类:
public class Test {
public static void main(String[] args) {
IPerson person = new Person();
PersonProxy personProxy = new PersonProxy(person);
IPerson per = personProxy.getProxy();
//当用代理对象调用方法时,实际上调用与代理对象关联的InvocationHandler的invoke(),并不是自己真实调用
per.test("测试数据");
}
}
执行结果:
start......
test......测试数据
end......
接下来看一个简单aop的配置文件:
<bean id="person" class="com.aop.Person"/>
<bean id="things" class="com.aop.Things"/>
<aop:config>
<aop:aspect id="thing" ref="things">
<aop:pointcut id="addMethod" expression="execution(* com.aop.IPersonDao.*(..))"/>
<aop:before method="wear" pointcut-ref="addMethod"/>
<aop:after method="working" pointcut-ref="addMethod"/>
</aop:aspect>
</aop:config>
</bean>
配置文件意思:在执行IPersonDao的所有方法前执行things.wear()方法,在执行IPersonDao的所有方法后执行things.working()方法
因此,我们就可以把上面代码的
System.out.println("start...... ") 替换成things.wear()(利用IOC的反射原理),
System.out.println("end......")替换成things.working()(利用IOC的反射原理).