Java中的动态代理与AOP编程
大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!今天我们将探讨Java中的动态代理和面向切面编程(AOP),这两者是构建灵活且可扩展系统的重要工具。
1. 动态代理概述
在Java中,动态代理允许我们在运行时创建代理对象,从而可以在不修改现有代码的情况下增强或替换对象的行为。Java的动态代理有两种类型:JDK动态代理和CGLIB代理。
1.1 JDK动态代理
JDK动态代理适用于接口代理。我们可以通过实现InvocationHandler
接口来定义代理逻辑。以下是一个使用JDK动态代理的示例。
UserService.java
package cn.juwatech.proxy;
public interface UserService {
void addUser(String user);
void deleteUser(String user);
}
UserServiceImpl.java
package cn.juwatech.proxy;
public class UserServiceImpl implements UserService {
@Override
public void addUser(String user) {
System.out.println("Adding user: " + user);
}
@Override
public void deleteUser(String user) {
System.out.println("Deleting user: " + user);
}
}
LoggingInvocationHandler.java
package cn.juwatech.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class LoggingInvocationHandler implements InvocationHandler {
private final Object target;
public LoggingInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Method " + method.getName() + " is called with arguments " + (args != null ? args[0] : "[]"));
return method.invoke(target, args);
}
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(
userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),
new LoggingInvocationHandler(userService)
);
proxy.addUser("John Doe");
proxy.deleteUser("John Doe");
}
}
1.2 CGLIB代理
CGLIB代理不需要接口,而是通过继承目标类来实现代理。以下是一个CGLIB代理的示例。
UserServiceCglib.java
package cn.juwatech.proxy;
public class UserServiceCglib {
public void addUser(String user) {
System.out.println("Adding user: " + user);
}
public void deleteUser(String user) {
System.out.println("Deleting user: " + user);
}
}
LoggingMethodInterceptor.java
package cn.juwatech.proxy;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class LoggingMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Method " + method.getName() + " is called with arguments " + (args != null ? args[0] : "[]"));
return proxy.invokeSuper(obj, args);
}
public static void main(String[] args) {
UserServiceCglib userService = new UserServiceCglib();
UserServiceCglib proxy = (UserServiceCglib) new org.springframework.cglib.proxy.Enhancer() {{
setSuperclass(UserServiceCglib.class);
setCallback(new LoggingMethodInterceptor());
}}.create();
proxy.addUser("John Doe");
proxy.deleteUser("John Doe");
}
}
2. 面向切面编程(AOP)
AOP允许我们在不改变业务逻辑代码的情况下,添加额外的横切关注点,如日志、事务等。Spring AOP是基于代理的,因此它可以使用JDK动态代理或CGLIB代理来实现。
2.1 配置Spring AOP
我们需要在Spring Boot应用中添加AOP相关依赖,并配置AOP切面。
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
LoggingAspect.java
package cn.juwatech.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class LoggingAspect {
@Before("execution(* cn.juwatech.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("Before method: " + joinPoint.getSignature().getName());
}
@After("execution(* cn.juwatech.service.*.*(..))")
public void logAfter(JoinPoint joinPoint) {
System.out.println("After method: " + joinPoint.getSignature().getName());
}
}
2.2 创建服务类
创建一个简单的服务类,并确保它在切面中被拦截。
UserService.java
package cn.juwatech.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void addUser(String user) {
System.out.println("Adding user: " + user);
}
public void deleteUser(String user) {
System.out.println("Deleting user: " + user);
}
}
2.3 启动Spring Boot应用
创建主类以启动Spring Boot应用并测试AOP功能。
AopDemoApplication.java
package cn.juwatech.aopdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AopDemoApplication {
public static void main(String[] args) {
SpringApplication.run(AopDemoApplication.class, args);
}
}
测试AOP功能
AopTest.java
package cn.juwatech.aopdemo;
import cn.juwatech.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class AopTest implements CommandLineRunner {
@Autowired
private UserService userService;
@Override
public void run(String... args) {
userService.addUser("John Doe");
userService.deleteUser("John Doe");
}
}
3. 总结
本文介绍了Java中的动态代理和面向切面编程(AOP),包括如何使用JDK动态代理和CGLIB代理实现代理功能,以及如何在Spring Boot应用中使用AOP进行横切关注点的管理。通过示例代码,我们展示了如何实现动态代理,并利用Spring AOP在应用中添加日志功能。这些技术可以大大增强应用的灵活性和可维护性。