代理模式简介分类
概念
代理,是为了在不修改目标对象的基础上,增强目标方法的业务逻辑。
客户类需要执行的是目标对象的目标方法,但是真正执行的是代理对象的代理方法,客户类对目标对象的访问是通过代理对象来实现的。当然,代理类与目标类需要实现同一个接口。
举例
生活中遇到了官司,我们平常老百姓对法律的了解不全面,所以一般都会请律师处理。
目标对象:法庭上我们一般称为当事人即目标对象
代理类:律师称为代理律师即代理类
共同接口:都为了一个共同的目标努力赢得官司即为共同接口
目标方法:我们所做的提供证据各种努力成为目标方法
代理方法:再此过程中我们可能做不全面,律师对证据材料等进行整理收集,结合法律法规进行辩证等等,此过程称为代理方法
代理分类
代理模式一般分为静态代理与动态代理,动态代理又分为JDK动态代理与CGLIB动态代理
静态代理
概念
静态代理是指,代理类在程序运行前就已经定义好,其与目标类等关系在程序运行前就已经确立。
静态代理类似于富翁于私人律师的代理关系,并不是在发生官司之后才去请律师,而是在此之前已经确立好的代理关系。
实现与解析
a、定义业务接口
package com.rangers.proxy.staticProxy; /** * @Author Rangers * @Description * @Date 2021-03-09 **/ public interface IAccountService { // 转账业务接口 void transfer(); }b、定义目标类与目标方法
package com.rangers.proxy.staticProxy; /** * @Author Rangers * @Description * @Date 2021-03-09 **/ public class AccountServiceImpl implements IAccountService { // 转账业务实现即目标方法 @Override public void transfer() { System.out.println("进行转账操作"); } }c、定义代理类AccountServiceImplProxy,实现IAccountService接口。在有参构造方法中传入目标对象,将目标对象引入代理类,以便代理类调用目标方法,进行增强
package com.rangers.proxy.staticProxy; /** * @Author Rangers * @Description * @Date 2021-03-09 **/ public class AccountServiceImplProxy implements IAccountService { // 声明目标接口对象 private IAccountService target; public AccountServiceImplProxy() { } // 业务接口对象作为构造器,用于接收目标对象 public AccountServiceImplProxy(IAccountService target) { this.target = target; } @Override public void transfer() { // 此处对目标方法进行增强 System.out.println("对转账人身份校验。。"); target.transfer(); System.out.println("进行日志记录。。"); } }d、编写测试类TransferServiceTest
package com.rangers.proxy.staticProxy; /** * @Author Rangers * @Description * @Date 2021-03-09 **/ public class TransferServiceTest { public static void main(String[] args) { // 创建目标对象 IAccountService target = new AccountServiceImpl(); // 创建代理对象,传入目标对象进行初始化 IAccountService proxy = new AccountServiceImplProxy(target); // 执行代理对象的方法 proxy.transfer(); } }
动态代理
动态代理,程序在整个运行过程中根本就不存在目标类的代理类,目标对象的代理对象只是由代理工具在程序运行时由JVM根据反射等机制动态生成。代理对象与目标对象的代理关系在程序运行时才确立。
动态代理类似于普通人在有官司之后,再聘请律师的,即代理关系是在官司发生后确立的。
动态代理的实现方式有两种:JDK的动态代理、CGLIB动态代理
a、JDK动态代理
概念
JDK动态代理是通过JDK提供的 java.lang.reflect.Proxy类实现动态大力,使用其静态方法newProxyInstance(),对目标对象、业务接口及业务增强逻辑,自动生成一个动态代理对象。
public static newProxyInstance(ClassLoader classLoader,Class<?> interfaces,InvocationHandler handler) classLoader:传入目标类的类加载器,通过目标对象的反射获取 interfaces:目标对象实现的接口数组,通过目标对象的反射获取 handler:业务增强逻辑,需要具体实现 InvocationHandler是个接口,实现InvocationHandler接口的类用于增加目标类的业务逻辑。需要实现invoke()方法,具体的增强逻辑就是在此方法中进行实现,程序调用住业务逻辑时会自动调用invoke()方法
public Object invoke(Object proxy,Method method,Object[] args) proxy:生成的代理对象 method:目标方法 args:目标方法的参数 Method类对象,invoke()方法进行执行目标对象的目标方法
public Object invoke(Object obj,Object args) method.invoke(Object target,Object...args)执行目标方法 target:目标对象 args:目标方法的执行参数
实现与解析
定义业务接口与实现类
package com.rangers.proxy.jdkProxy; /** * @Author Rangers * @Description * @Date 2021-03-09 **/ public interface IAccountService { // 转账业务接口 void transfer(); } package com.rangers.proxy.jdkProxy; /** * @Author Rangers * @Description * @Date 2021-03-09 **/ public class AccountServiceImpl implements IAccountService { // 转账业务实现即目标方法 @Override public void transfer() { System.out.println("进行转账操作"); } }