在面向对象编程中,代理模式是一种常见的设计模式,用于在不改变目标对象的前提下对其功能进行扩展。而面向切面编程(AOP)进一步通过代理模式,将横切关注点(如日志记录、事务管理等)与业务逻辑分离,从而实现更为优雅和模块化的设计。本文将详细介绍静态代理、动态代理(包括JDK动态代理和CGLIB动态代理)的实现方式,并进一步探讨AOP的原理及其在Spring中的应用。
静态代理是指在代码中显式地创建代理类,代理类与目标对象实现相同的接口,并通过代理类的方法对目标对象进行增强。静态代理的优点在于可以在不修改目标对象的前提下扩展其功能,然而其缺点是需要实现与目标对象相同的接口,导致代理类繁多,增加了维护成本。
目标对象:
public class Girl implements Human {
@Override
public void eat() {
System.out.println("Em mmm.. mm..");
}
}
抽象接口:
interface Human {
void eat();
}
代理类:
public class ProxyGirl implements Human {
private Human human;
public ProxyGirl(Human human) {
this.human = human;
}
@Override
public void eat() {
System.out.println("chiqian");
human.eat(); // 调用目标对象的方法
System.out.println("chihou");
}
}
测试类:
public class Main {
public static void main(String[] args) {
Girl girl = new Girl();
Human proxyGirl = new ProxyGirl(girl);
proxyGirl.eat(); // 输出增强后的方法
}
}
输出结果:
chiqian
Em mmm.. mm..
chihou
动态代理与静态代理不同,它是在运行时动态生成代理对象,而不是在编译时静态生成。动态代理有两种主要实现方式:基于JDK的动态代理和基于CGLIB的动态代理。
InvocationHandler
和Proxy
类实现。接口及其实现类:
// 定义接口
public interface MyInterface {
void doSomething();
}
// 实现接口
public class MyInterfaceImpl implements MyInterface {
@Override
public void doSomething() {
System.out.println("Doing something...");
}
}
InvocationHandler:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method execution.");
Object result = method.invoke(target, args);
System.out.println("After method execution.");
return result;
}
}
动态代理测试类:
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
MyInterfaceImpl myInterfaceImpl = new MyInterfaceImpl();
MyInvocationHandler handler = new MyInvocationHandler(myInterfaceImpl);
MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
MyInterface.class.getClassLoader(),
new Class<?>[]{MyInterface.class},
handler);
proxy.doSomething(); // 调用代理对象的方法
}
}
输出结果:
Before method execution.
Doing something...
After method execution.
目标类:
public class MyClass {
public void doSomething() {
System.out.println("Doing something in MyClass...");
}
}
MethodInterceptor:
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method execution.");
Object result = proxy.invokeSuper(obj, args); // 调用父类(被代理类)的方法
System.out.println("After method execution.");
return result;
}
}
CGLIB动态代理测试类:
import net.sf.cglib.proxy.Enhancer;
public class Main {
public static void main(String[] args) {
MyClass myClass = new MyClass();
MyMethodInterceptor interceptor = new MyMethodInterceptor();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MyClass.class); // 设置要代理的类
enhancer.setCallback(interceptor); // 设置回调函数
MyClass proxy = (MyClass) enhancer.create(); // 创建代理对象
proxy.doSomething(); // 调用代理对象的方法
}
}
输出结果:
Before method execution.
Doing something in MyClass...
After method execution.
使用CGLIB时,需要在Maven项目中添加CGLIB依赖:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version> <!-- 使用时请检查最新版本 -->
</dependency>
AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,旨在将横切关注点(如日志记录、事务管理、安全检查等)与业务逻辑分离开来,从而实现模块化的代码设计。AOP通过将横切关注点定义为的切面,并在特定的切入点上织入这些切面,来实现对目标对象方法的增强。
Spring AOP主要使用动态代理来实现AOP功能:
Spring AOP示例:
定义切面类:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class LoggingAspect {
// 切入点表达式,表示在com.example包下的所有方法执行前执行这个切面
@Before("execution(* com.example.*.*(..))")
public void logBefore() {
System.out.println("Before method execution.");
}
}
配置和使用切面:
将切面类配置到Spring应用上下文中,Spring会自动检测@Aspect
注解并在运行时动态创建代理对象,从而在方法执行前自动调用logBefore()
方法。
Spring AOP的优点:
和模块化程度。
通过本文对静态代理、动态代理以及AOP的详细介绍,可以看出代理模式在Java编程中的广泛应用。从静态代理的显式代码实现,到动态代理的运行时生成代理对象,再到AOP的高度模块化设计,代理模式不仅提升了代码的可维护性,还为横切关注点的处理提供了有效的手段。随着业务需求的复杂化,AOP在Spring等框架中的应用也愈发重要,使得代码更加优雅、灵活和可扩展。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- kqyc.cn 版权所有 赣ICP备2024042808号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务