代理模式(JDK,CGLIB动态代理,AOP切面编程)
代理模式是一种结构型设计模式,它通过一个代理对象作为中间层来控制对目标对象的访问,从而增强或扩展目标对象的功能,同时保持客户端对目标对象的使用方式一致。
代理模式在Java中的应用,例如
1.统一异常处理
2.Mybatis使用代理
3.Spring AOP实现原理
4.日志框架
讲些空话,大话,大白话:
接口:定义行为规范,为了多态
实现类:对具体接口的实现(目标对象),被代理的类
代理类:做功能增强与扩展
静态代理:(常用于代理接口的实现类,也可以代理普通类)
代理接口的实现类
定义接口
public interface Service {
void doWork();
}
实现目标对象
public class RealService implements Service {
@Override
public void doWork() {
System.out.println("RealService 正在执行工作。");
}
}
创建代理类
public class ServiceProxy implements Service {
private final Service realService; // 持有目标对象的引用//我还可以引入些其他,用来在doWork方法前后做增强或者扩展
//private Xxxx xxxx;可以构造中做初始化
public ServiceProxy(Service realService) {
this.realService = realService;
}@Override
public void doWork() {
System.out.println("代理:调用方法之前记录日志...");
realService.doWork(); // 调用目标对象的方法
System.out.println("代理:调用方法之后记录日志...");
}
}
测试静态代理
public class StaticProxyExample {
public static void main(String[] args) {
// 创建目标对象
Service realService = new RealService();// 创建代理对象,并传入目标对象
Service proxy = new ServiceProxy(realService);// 调用代理对象的方法
proxy.doWork();
}
}
静态代理在Boot中实际使用
---------------------------------------------------------------------------------------------------------------
代理普通类
// 目标类
public class RealService {
public void doWork() {
System.out.println("RealService 正在工作...");
}
}// 代理类
public class ServiceProxy {
private RealService realService;public ServiceProxy(RealService realService) {
this.realService = realService;
}public void doWork() {
System.out.println("代理: 调用方法之前...");
realService.doWork();
System.out.println("代理: 调用方法之后...");
}
}// 使用代理
public class Main {
public static void main(String[] args) {
RealService realService = new RealService();
ServiceProxy proxy = new ServiceProxy(realService);
proxy.doWork();
}
}
JDK动态代理
1.JDK 动态代理的特点
-
必须基于接口:
- 代理对象必须实现目标类的接口。
- 如果目标类没有接口,JDK 动态代理无法使用。
-
运行时动态生成代理对象:
- 代理类的代码不是在编译时生成,而是在运行时动态创建。
-
通过
InvocationHandler
实现增强逻辑:- 使用
InvocationHandler
接口处理方法的调用逻辑。 - 可以对方法调用进行拦截,并添加额外的增强功能。
- 使用
-
生成的代理类是目标接口的实现类:
- 代理对象的类型是接口类型,不能直接当作目标类使用。
2. JDK 动态代理的核心类
(1) Proxy
类
- Java 动态代理的核心类,用于生成代理对象。
- 方法:
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
ClassLoader loader
:目标类的类加载器,用于加载代理对象。Class<?>[] interfaces
:目标类实现的接口数组。InvocationHandler h
:调用处理器,用于定义代理对象的方法逻辑。
(2) InvocationHandler
接口
- 用于定义代理对象的行为。
- 核心方法:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
proxy
:代理对象本身。method
:当前调用的方法。args
:调用方法的参数。
3. JDK 动态代理的实现步骤
(1) 定义接口和实现类
// 定义接口
public interface Service {
void doWork();
}// 实现类(目标类)
public class RealService implements Service {
@Override
public void doWork() {
System.out.println("RealService 正在执行工作...");
}
}
(2) 创建 InvocationHandler 该接口作用是方法拦截
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class ServiceInvocationHandler implements InvocationHandler {
private Object target; // 持有目标对象的引用public ServiceInvocationHandler(Object target) {
this.target = target;
}@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理: 调用方法之前记录日志...");
Object result = method.invoke(target, args); // 调用目标方法
System.out.println("代理: 调用方法之后记录日志...");
return result;
}
}
(3) 创建代理对象
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
// 创建目标对象
Service realService = new RealService();// 创建 InvocationHandler
ServiceInvocationHandler handler = new ServiceInvocationHandler(realService);// 生成代理对象
Service proxy = (Service) Proxy.newProxyInstance(
realService.getClass().getClassLoader(), // 类加载器
new Class<?>[]{Service.class}, // 实现的接口
handler // 调用处理器
);// 调用代理对象的方法
proxy.doWork();
}
}