请使用JDK编写一个动态代理的实际应用案例代码。
参考回答
问题:使用JDK编写一个动态代理的实际应用案例代码。
下面我们将编写一个实际应用案例,使用JDK动态代理来实现一个日志功能。每当调用目标方法时,代理会在方法执行前后分别打印日志。我们会通过JDK的动态代理机制来完成这一功能。
详细讲解与拓展
1. 定义接口
首先,我们定义一个业务接口Service,它包含一个performAction方法,用于模拟实际业务操作。
public interface Service {
void performAction(String action);
}
2. 实现目标类
然后,我们定义一个目标类ServiceImpl,它实现了Service接口,并提供具体的业务逻辑。
public class ServiceImpl implements Service {
@Override
public void performAction(String action) {
System.out.println("Executing action: " + action);
}
}
3. 创建InvocationHandler
接下来,我们实现InvocationHandler接口,重写invoke()方法来实现代理逻辑。在invoke()方法中,我们添加日志功能,记录方法执行前后的日志。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ServiceInvocationHandler implements InvocationHandler {
private final Object target;
public ServiceInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 记录方法执行前的日志
System.out.println("Logging: Before invoking method " + method.getName());
// 执行目标方法
Object result = method.invoke(target, args);
// 记录方法执行后的日志
System.out.println("Logging: After invoking method " + method.getName());
return result;
}
}
4. 创建代理对象
使用Proxy.newProxyInstance()方法来创建代理对象。我们将ServiceImpl作为目标对象,通过InvocationHandler来为其添加日志功能。
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
// 创建目标对象
Service service = new ServiceImpl();
// 创建 InvocationHandler
ServiceInvocationHandler handler = new ServiceInvocationHandler(service);
// 创建代理对象
Service proxy = (Service) Proxy.newProxyInstance(
service.getClass().getClassLoader(), // 类加载器
new Class[]{Service.class}, // 目标对象实现的接口
handler // InvocationHandler
);
// 调用代理对象的方法
proxy.performAction("Sample Action");
}
}
5. 输出结果
Logging: Before invoking method performAction
Executing action: Sample Action
Logging: After invoking method performAction
代码解析
- 接口定义:
Service接口声明了performAction方法,表示我们的目标业务操作。 - 目标类实现:
ServiceImpl类实现了Service接口,并提供了具体的业务逻辑。 - InvocationHandler:
ServiceInvocationHandler类实现了InvocationHandler接口。在invoke()方法中,我们添加了日志功能,记录方法执行前后的日志,然后通过method.invoke(target, args)调用目标对象的方法。 - 代理对象创建:在
ProxyTest类中,我们使用Proxy.newProxyInstance()创建代理对象。newProxyInstance方法的参数包括目标类的类加载器、目标类实现的接口以及我们的InvocationHandler实例。
总结
通过以上代码,我们使用了JDK动态代理来实现日志功能。每当调用proxy.performAction("Sample Action")时,代理对象会拦截该方法调用,并在方法执行前后输出日志。JDK动态代理非常适合用来为接口方法添加统一的横切逻辑,例如日志记录、权限校验、性能监控等。