0、前言
代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。
1、静态代理
静态代理是一种代理模式的实现方式,它在编译期间就已经确定了代理对象,需要为每一个被代理对象创建一个代理类。静态代理的实现比较简单,但是每个被代理对象都需要创建一个代理类,因此在代理对象比较多时,会导致代码几余和维护成本增加。
静态代理有两种实现,继承和聚合两种模式。
1.1、继承模式
需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者继续相同父类,代理对象继承目标对象,重新目标对象的方法。
目标对象:
package proxy.staticproxy.extends_model;
//目标对象
public class UserService {
public void login(){
System.out.println("login success");
}
}
代理类:
package proxy.staticproxy.extends_model;
//代理对象
public class UserServiceProxy extends UserService{
public void login(){
System.out.println("开始执行--------------");
super.login();
}
}
测试类:
package proxy.staticproxy;
import proxy.staticproxy.extends_model.UserServiceProxy;
import proxy.staticproxy.implements_model.FactoryOne;
import proxy.staticproxy.implements_model.FactoryOneProxy;
import proxy.staticproxy.implements_model.IFactory;
public class Test {
@org.junit.Test
public void extends_model(){
UserServiceProxy proxy = new UserServiceProxy();
proxy.login();
}
// 待代理类来处理
/// 场景:当不想改动被代理类的业务逻辑,在处理开始和结束分别加上时间显示
/// 处理核心逻辑:需要实现被代理类的接口及方法,在实现方法中田间需要添加的业务处理逻辑
@org.junit.Test
public void implements_model(){
// 创建被代理类的对象
IFactory word = new FactoryOne();
// 创建代理类的对象
IFactory proxyPaperFactory = new FactoryOneProxy(word);
proxyPaperFactory.production();
}
// 直接调用被代理类业务处理
@org.junit.Test
public void test01(){
// 创建被代理类的对象
IFactory word = new FactoryOne();
word.production();
}
}
执行结果:
开始执行--------------
login success
1.2、聚合模式
Subject:抽象主题角色,抽象主题类可以是抽象类,也可以是接口,是一个最普通的业务类型定义,无特殊要求。
RealSubject:具体主题角色,也叫被委托角色、被代理角色。是业务逻辑的具体执行者。
Proxy:代理主题角色,也叫委托类、代理类。它把所有抽象主题类定义的方法给具体主题角色实现,并且在具体主题角色处理完毕前后做预处理和善后工作。
Subject 接口:
package proxy.staticproxy.implements_model;
public interface IFactory {
void production();
}
RealSubject 类:
package proxy.staticproxy.implements_model;
public class FactoryOne implements IFactory {
@Override
public void production() {
System.out.println(" 被代理类,开始初始化 ");
System.out.println(" 生产笔记本、鼠标、键盘等等 ");
System.out.println(" 被代理类处理完成 ");
}
}
Proxy 类:
package proxy.staticproxy.implements_model;
public class FactoryOneProxy implements IFactory {
private IFactory factory; // 用被代理类对象进行实例化
public FactoryOneProxy(IFactory factory) {
this.factory = factory;
}
@Override
public void production() {
System.out.println(" 代理开始工作 ,在此可以添加处理逻辑");
factory.production();
System.out.println(" 代理结束工作 ,在此可以添加处理逻辑");
}
}
测试类:
package proxy.staticproxy;
import proxy.staticproxy.extends_model.UserServiceProxy;
import proxy.staticproxy.implements_model.FactoryOne;
import proxy.staticproxy.implements_model.FactoryOneProxy;
import proxy.staticproxy.implements_model.IFactory;
public class Test {
@org.junit.Test
public void extends_model(){
UserServiceProxy proxy = new UserServiceProxy();
proxy.login();
}
// 待代理类来处理
/// 场景:当不想改动被代理类的业务逻辑,在处理开始和结束分别加上时间显示
/// 处理核心逻辑:需要实现被代理类的接口及方法,在实现方法中田间需要添加的业务处理逻辑
@org.junit.Test
public void implements_model(){
// 创建被代理类的对象
IFactory word = new FactoryOne();
// 创建代理类的对象
IFactory proxyPaperFactory = new FactoryOneProxy(word);
proxyPaperFactory.production();
}
// 直接调用被代理类业务处理
@org.junit.Test
public void test01(){
// 创建被代理类的对象
IFactory word = new FactoryOne();
word.production();
}
}
运行结果:
代理开始工作 ,在此可以添加处理逻辑
被代理类,开始初始化
生产笔记本、鼠标、键盘等等
被代理类处理完成
代理结束工作 ,在此可以添加处理逻辑
2、动态代理
动态代理是一种代理模式的实现方式,它在运行期间根据需要动态生成代理对象,无需手动编写代理类,可以减少代码几余和维护成本。动态代理适用于需要代理的对象数量较多,代理类实现对灵活的场景,例Spring框架中的Spring AOP(面向切面编程)功能。
动态代理的实现方式也有两种,JDK动态代理和CGLB动态代理两种模式。本文重点介绍JDK动态代理,
在JDK中,有一个Proxy类(名词,代理人)。Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态的生成实现类。Proxy类提供的有一个静态方法:newProxyInstance()方法给我们的目标对象(委托对象)返回一个代理对象。
核心方法:newProxyInstance方法的三个参数,按照顺序分别是 ClassLoader (类加载器),interfaces(一组接口,接口数组),InvocationHandler(调用处理器)。
ClassLoader (类加载器)
定义了由哪个classLoader对象来对生成的代理对象进行加载。
接口数组:
一个Interface对象的数组,表示将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了。
调用处理器:
一个InvocationHandler接口,表示代理实例的调用处理程序实现的接口。每个代理实例都具有一个关联的调用处理程席。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法(传入InvocationHandler接口的子类)。
对象接口:
package proxy.dynamicproxy.v3;
public interface IAnimal {
public void run();
public void eat();
public void sleep();
}
被代理类<Cat>:
package proxy.dynamicproxy.v3;
public class Cat implements IAnimal{
@Override
public void run() {
System.out.println("Cat Run invoking!!!");
}
@Override
public void eat() {
System.out.println("Cat eat invoking!!!");
}
@Override
public void sleep() {
System.out.println("Cat sleep invoking!!!");
}
}
被代理类<Dog>:
package proxy.dynamicproxy.v3;
public class Dog implements IAnimal{
@Override
public void run() {
System.out.println("Dog Run invoking!!!");
}
@Override
public void eat() {
System.out.println("Dog eat invoking!!!");
}
@Override
public void sleep() {
System.out.println("Dog sleep invoking!!!");
}
}
代理类工具类:
package proxy.dynamicproxy.v3;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyUtils {
public Object object;
public ProxyUtils(Object object) {
this.object = object;
}
public Object createProxyObj(){
// 动态代理 顾名思义 针对接口动态生成代理类处理业务逻辑
// 返回动态代理
/*
ClassLoader loader, 要实现接口的类加载器
Class<?>[] interfaces,接口类
InvocationHandler h 处理类
* **/
ClassLoader loader = object.getClass().getClassLoader();
// Class<?>[] interfaces = new Class[]{argObj.getClass()}; // 当是接口
Class<?>[] interfaces = object.getClass().getInterfaces(); // 当是类直接获取对应的接口方法;
InvocationHandler handler = new IFactoryInvocationHandler();
Object object = Proxy.newProxyInstance(loader, interfaces, handler);
return object;
}
public class IFactoryInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("IFactoryInvocationHandler invoke Before!!!");
Object rtn = method.invoke(object, args);
System.out.println("IFactoryInvocationHandler invoke After!!!");
return rtn;
}
}
}
测试类:
package proxy.dynamicproxy;
import proxy.dynamicproxy.v3.Cat;
import proxy.dynamicproxy.v3.IAnimal;
import proxy.dynamicproxy.v3.ProxyUtils;
public class Test {
@org.junit.Test
public void v3_common_test() {
// 实例化代理工具类
ProxyUtils proxyUtils = new ProxyUtils(new Cat());
// 创建代理对象
IAnimal animal = (IAnimal)proxyUtils.createProxyObj();
// 调用被代理类的方法
animal.eat();
System.out.println("========================================================");
animal.run();
System.out.println("========================================================");
animal.sleep();
System.out.println("========================================================");
}
}
运行结果:
IFactoryInvocationHandler invoke Before!!!
Cat eat invoking!!!
IFactoryInvocationHandler invoke After!!!
========================================================
IFactoryInvocationHandler invoke Before!!!
Cat Run invoking!!!
IFactoryInvocationHandler invoke After!!!
========================================================
IFactoryInvocationHandler invoke Before!!!
Cat sleep invoking!!!
IFactoryInvocationHandler invoke After!!!
========================================================
Process finished with exit code 0
3、动态代理原理
JDK动态代理是一种实现代理模式的方式。它利用Java的反射机制,在运行时动态地创建代理对象,实现对目标对象的代理。
JDK动态代理的原理如下:
定义接口:首先需要定义一个接口,用于描述目标对象和代理对象的共同行为。
实现InvocationHandler接口:创建一个实现InvocationHandler接口的代理处理器类,该类负责对目标对象的方法进行代理。
获取代理类:通过java.lang.reflect.Proxy的静态方法newProxyInstance()创建代理类,该方法需要传入ClassLoader、接口数组和InvocationHandler实例。
调用代理对象:通过代理对象调用方法时,实际上是调用InvocationHandler的invoke()方法。
在invoke()方法中,可以进行一些额外的操作,比如在调用目标方法之前进行预处理、在调用目标方法后进行后处理等。