3.AOP解析-代理模式 总览
参考狂神说MyBatis课程笔记
参考黑马程序员Spring课程笔记
Spring笔记思维导图:
问题扩展与汇总:
1. 静态代理
1.1 代理模式解析
- 是实现AOP机制的底层机制
- 分为静态代理和动态代理
- 总的分为四个部分:
- 抽象角色
- 一般使用接口或者抽象类来实现,实现特定功能
- 例如租房这种需求
- 真实角色
- 被代理的角色,例如房东角色,可以提供租房这种需求
- 代理角色:Proxy
- 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作
- 例如可以帮助房东租房,还可以有其他增强功能,例如看房、收取中介费等功能
- 客户: 通过代理角色实现真实角色有关抽象角色中的功能和增强功能
- 抽象角色
1.2 静态代理举例
-
Rent接口:即抽象角色
//抽象角色:租房 public interface Rent { public void rent(); }
-
Host类:即真实角色
//真实角色: 房东,房东要出租房子 public class Host implements Rent{ public void rent() { System.out.println("房屋出租"); } }
-
Proxy类:即代理角色
//代理角色:中介 public class Proxy implements Rent { private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } //租房 public void rent(){ seeHouse(); host.rent(); fare(); } //看房 public void seeHouse(){ System.out.println("带房客看房"); } //收中介费 public void fare(){ System.out.println("收中介费"); } }
-
Client类:即客户
//客户类,一般客户都会去找代理! public class Client { public static void main(String[] args) { //房东要租房 Host host = new Host(); //中介帮助房东 Proxy proxy = new Proxy(host); //你去找中介! proxy.rent(); } }
1.3 静态代理好处
- 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
- 减少代码的耦合度
- 公共的业务由代理来完成 . 实现了业务的分工 ,
- 公共业务发生扩展时变得更加集中和方便 .
缺点 :
- 类多了 , 多了代理类 , 工作量变大了 . 开发效率降低 .
我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理 !
AOP思想:
我们在不改变原来的代码的情况下,实现了对原有功能的增强,这是AOP中最核心的思想
2. 动态代理
2.1 理解与分类
- 动态代理的角色和静态代理的一样 .
- 动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
- 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
- 基于接口的动态代理——JDK动态代理
- 基于类的动态代理—cglib
- 现在用的比较多的是 javasist 来生成动态代理
2.2 JDK的动态代理
InvocationHandler
- 此接口是代理对象的处理程序,即告知怎么处理
invoke()
-
反射机制的函数激活
-
invoke()中的method会自动对应代理对象实例proxy要调用的方法
-
即,dao层的增删改查方法,proxy调用add()方法,method就对应add()方法
-
Object invoke(Object proxy, 方法 method, Object[] args);
//参数
//proxy - 调用该方法的代理实例
//method -所述方法对应于调用代理实例上的接口方法的实例。
//args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。 原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。
Proxy
newProxyInstance()
- Proxy的静态方法,可以直接通过超类Proxy创建这个方法,来创建代理对象
ClassLoader loader,
- 与被代理对象相同的类加载器
- 即,如果传入的就是被代理类的接口,就用这个类的类加载器
- 如果这个方法和被代理对象定义在一个类中,例如InvocationHandler实现类中,就是这个类的加载器
类<?>[] interfaces,
- 代理对象要实现的接口:即抽象角色的接口
InvocationHandler h)
- 如何代理:即InvocationHandler的实现类,invoke方法
实例
核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!、
我们来使用动态代理实现代理我们后面写的UserService!
我们也可以编写一个通用的动态代理实现的类!所有的代理对象设置为Object即可!
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(),this);
}
// proxy : 代理类
// method : 代理类的调用处理程序的方法对象.
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
Object result = method.invoke(target, args); // 再次反射,激活method方法
return result;
}
public void log(String methodName){
System.out.println("执行了"+methodName+"方法");
}
}
测试!
public class Test {
public static void main(String[] args) {
//真实对象
UserServiceImpl userServiceImpl = new UserServiceImpl();
//代理对象的调用处理程序
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(userServiceImpl); //设置要代理的对象-父类引用指向子类对象
UserService proxy = (UserService)pih.getProxy(); //动态生成代理类!
proxy.delete();
}
}
2.3 动态代理的好处
静态代理有的它都有,静态代理没有的,它也有!
- 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
- 公共的业务由代理来完成 . 实现了业务的分工 ,
- 公共业务发生扩展时变得更加集中和方便 .
- 一个动态代理 , 一般代理某一类业务
- 一个动态代理可以代理多个类,代理的是接口
2.4 Mybaits中,SqlSession创建代理接口的代理对象

- 创建代理对象