spring aop的底层原理就是动态代理模式:
代理模式分成两种:1.静态代理模式2.动态代理模式
所谓静态代理就是在运行程序前,程序员手动创建好了代理类,之后运行程序。而动态代理类是通过反射机制,在运行程序的时候,由Java的虚拟机创建出一个代理类。无需程序员手动敲代码,减少了工作的复杂性。
动态代理模式
举例:
动物都有会叫的方法,这时一只猫会叫,这是我需要调猫的shout(叫)的方法。代码如下:
//接口
public interface Animal {
public void shout();
}
//猫实现动物会叫的接口,并重写shout方法
public class Cat implements Animal{
@Override
public void shout() {
System.out.println("我是一只猫,我正在叫~~~miao");
}
}
//junit注解,运行程序,创建一只猫,让它叫····
public class TestShout {
@Test
public void test1(){
Animal animal=new Cat();
animal.shout();
}
}
结果轻松愉快的叫了一声 miao~~~现在同样的例子,我们可以通过实现动物接口,重写方法让狗叫,鸡叫,都可以。这也是比较简单的事情。现在,需求上升,需要每个动物叫之前自报家门,叫之后告诉我们叫完了。如何实现:
1.直接在接口的实现类中增加方法
public class Cat implements Animal{
@Override
public void shout() {
before();
System.out.println("我是一只猫,我正在叫~~~miao");
after();
}
//创建两个方法,添加到shout方法
public void before(){
System.out.println("我叫张天爸,来自西域!");
}
public void after(){
System.out.println("叫完了,你可以睡觉了!");
}
}
好像解决了~~~
但这是会有一个问题,如果动物园每只都要以这种方式叫上一遍,岂不是要累死程序员,就算将方法抽出,也需要在实现类中调方法(怪不得程序员头发这么少)。
这时就介绍我们今天的主角,通过动态代理模式来实现:
同样是猫叫的方法,创建动态代理类,Proxy
public class ProxyAnimal implements InvocationHandler {
//创建猫的对象
private Animal animal;
//必须要写带参构造方法
public ProxyAnimal(Animal animal) {
this.animal=animal;
}
//在实现InvocationHandler类的时候需要重写invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//shout方法执行前要做的事
System.out.println("我来自黄土高坡");
method.invoke(animal,args);
//shout方法之后要做的事
System.out.println("不吹牛逼啦,我要睡觉");
return null;
}
}
好像也不是很难理解,method.invoke是执行被代理的对象的方法,如果有返回值,可以通过return传递,Object[] args,是被代理对象中的参数集合,至于Object proxy是一个很重要的东西,不要随便改就对啦。(我吧,我承认我不了解🐕,回头弄明白之后一定补上。。。。)
剩下的就是调方法执行程序
public class TestProxyShout {
Animal animal=new Cat();
@Test
public void test1(){
Animal cat = (Animal) Proxy.newProxyInstance(animal.getClass().getClassLoader(),
animal.getClass().getInterfaces(),
new ProxyAnimal(animal));
cat.shout();
}
}
/*
*
* Proxy.newProxyInstance();
* 第一个参数被代理类的classloader
* 第二个参数是被代理类的所有接口
* 第三个参数是处理类
*
* */
动态代理模式完成!
动态代理模式的优点在于,不改变原有的代码实现代理功能。(工作中去改别人的代码是一件很讨厌的事情😡),代理逻辑与业务逻辑是互相独立的,没有耦合,代理1个类100个类没有任何区别。但是写起来还是有点繁琐,所以,Spring框架帮我们完成了这件事情,传说中的AOP面向切面编程思想。底层就是动态代理。