一、代理模式和静态代理
1.1代理模式
代理模式
- Proxy Pattern, 23个经典模式的一种,又称委托模式
-为目标对象提供(包装)了一个代理,这个代理可以控制对目标对象的访问
- 外界不用直接访问目标对象,而是访问代理对象,由代理对象再调用目标对象
- 代理对象中可以添加监控和审查处理
- David Wheeler(函数的发明者):All problems in computer science can be solved by another level of indirection。
1.2静态代理
1.3静态代理代码演示
package org.example;public interface Subject{public void request();
}
package org.example;//目标对象
class SubjectImpl implements Subject {public void request() {System.out.println("I am dealing the request.");}
}
package org.example;//代理对象
class StaticProxy implements Subject{//实际目标对象private Subject subject;public StaticProxy(Subject subject){this.subject = subject;}public void request(){System.out.println("PreProcess");subject.request();System.out.println("PostProcess");}
}
package org.example;//静态代理模式
public class StaticProxyDemo {public static void main(String args[]) {
//创建实际对象SubjectImpl subject = new SubjectImpl();
//把实际对象封装到代理对象中StaticProxy p = new StaticProxy(subject);p.request();}
}
二、动态代理
2.1代理处理器
-持有目标对象的句柄
- 实现InvocationHandler接口
- 实现invoke方法
- 所有的代理对象方法调用,都会转发到invoke方法来
- invoke的形参method,就是指代理对象方法的调用
- 在invoke内部,可以根据method,使用目标对象不同的方法来响应请求
2.2代码示例
package org.example;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// 创建一个接口,将会被代理
interface Calculator {int add(int a, int b);
}// 创建一个实现了 InvocationHandler 接口的代理处理器类
class CalculatorInvocationHandler implements InvocationHandler {private Object target; // 被代理的对象public CalculatorInvocationHandler(Object target) {this.target = target;}// 实现 invoke 方法,用于处理代理对象上的方法调用public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 在调用被代理对象的方法之前可以执行一些逻辑System.out.println("Before invoking " + method.getName());// 使用 Java 反射调用被代理对象上的方法Object result = method.invoke(target, args);// 在调用被代理对象的方法之后可以执行一些逻辑System.out.println("After invoking " + method.getName());return result; // 返回方法的结果}
}public class DynamicProxyHandlerExample {public static void main(String[] args) {// 创建被代理的对象Calculator realCalculator = new Calculator() {public int add(int a, int b) {return a + b;}};// 创建代理处理器对象CalculatorInvocationHandler handler = new CalculatorInvocationHandler(realCalculator);// 使用 Proxy 类生成代理对象Calculator proxy = (Calculator) Proxy.newProxyInstance(Calculator.class.getClassLoader(),new Class[]{Calculator.class},handler);// 调用代理对象的方法int result = proxy.add(5, 3);System.out.println("Result: " + result);}
}
2.3代理对象
三、AOP编程
AOP编程是一种软件开发技术,它可以将横切关注点(cross-cutting concerns)从业务逻辑中分离出来,实现代码的模块化和复用。横切关注点是指那些影响了多个类或方法的功能,例如日志、安全、事务等。AOP通过在运行时或编译时动态地将切面(aspect)织入到目标对象中,来增强目标对象的功能。切面是由通知(advice)和切点(pointcut)组成的,通知定义了切面要做什么,切点定义了切面要在哪里做。
3.1优点
- 可以提高代码的可读性和可维护性,因为横切关注点被集中在一个地方,而不是分散在多个类或方法中。
- 可以提高代码的复用性和扩展性,因为横切关注点可以被重用和修改,而不影响业务逻辑的核心功能。
- 可以提高代码的稳定性和安全性,因为横切关注点可以对业务逻辑进行统一的处理,例如异常处理、事务管理等。
3.2常见应用场景
- 日志记录:可以在方法的执行前后记录日志,方便调试和监控。
- 权限检查:可以在方法的执行前检查用户的权限,防止非法访问。
- 缓存管理:可以在方法的执行后将结果缓存起来,提高性能。
- 性能统计:可以在方法的执行前后统计执行时间,优化性能。
- 事务管理:可以在方法的执行前后进行事务的开启和提交,保证数据的一致性
3.3哪些框架使用了AOP
AOP是一种软件开发技术,它可以将横切关注点(cross-cutting concerns)从业务逻辑中分离出来,实现代码的模块化和复用。在Java中,有很多框架使用了AOP,例如:
- Spring Framework:Spring Framework是一个提供了全面的编程和配置模型的Java企业级应用开发框架1。Spring Framework支持AOP,可以让开发者通过注解或XML配置的方式,定义切面(aspect)和切点(pointcut),并将它们织入到目标对象中,实现功能的增强2。Spring Framework的AOP模块主要基于动态代理(dynamic proxy)技术,也可以使用AspectJ编译器来实现静态织入(static weaving)。
- AspectJ:AspectJ是一个基于Java语言的AOP框架,它扩展了Java语法,引入了新的关键字和语法结构,让开发者可以直接在源代码中定义切面和切点,并通过AspectJ编译器将它们编译成字节码。AspectJ提供了更强大和灵活的AOP功能,可以支持更多种类的切点和通知(advice),例如构造器调用、字段读写、异常处理等。
- Guice:Guice是一个轻量级的依赖注入(dependency injection)框架,它可以让开发者通过注解的方式,声明对象之间的依赖关系,并自动创建和管理对象的生命周期。Guice也支持AOP,可以让开发者通过@Interceptor注解,定义方法拦截器(method interceptor),并将它们绑定到指定的切点上,实现功能的增强。Guice的AOP模块基于动态代理技术,只能拦截接口方法或非final类方法。