我们这里使用JDK的原生代码来实现,其余的道理都是一样的!
JDK的动态代理需要了解两个类:
核心:InvocationHandler 和 Proxy,打开JDK帮助文档看看
【InvocationHandler:调用处理程序】
invoke
方法。 public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
// 参数解释:
// proxy -- 代理角色
// method -- 代理角色调用的方法
// args -- 代理角色调用的方法传递的参数
【Proxy : 代理】
Proxy
提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
为某个接口创建代理实例
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
// 参数解释:
// loader -- 类加载器
// interfaces -- 代理类实现的接口列表
// h -- 调用处理程序
代码实现
抽象角色和真实角色和之前的一样!
1、Rent . java 即抽象角色
package com.edgar.demo03;
// 抽象角色:租房
public interface Rent {
void rent();
}
2、LangLord. java 即真实角色
package com.edgar.demo03;
//真实角色: 房东,房东要出租房子
public class LangLord implements Rent {
@Override
public void rent() {
System.out.println("房东要出租房子!");
}
}
3、ProxyInvocationHandler. java 即代理角色
package com.edgar.demo03;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 等会我们会用这个类,自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
// 被代理的接口
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
// 生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
this.rent.getClass().getInterfaces(),this);
}
// 处理代理实例,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的本质,就是使用反射机制实现!
this.seeHouse();
Object result = method.invoke(this.rent, args);
this.fare();
return result;
}
public void seeHouse(){
System.out.println("中介带看房子");
}
public void fare(){
System.out.println("收中介费");
}
}
4、Client . java
package com.edgar.demo03;
public class Client {
public static void main(String[] args) {
// 真实角色
LangLord langLord = new LangLord();
// 代理实例的调用程序
ProxyInvocationHandler pih = new ProxyInvocationHandler();
// 将真实角色放置进去
pih.setRent(langLord);
// 动态生成对应的代理类!
Rent proxy = (Rent) pih.getProxy();
proxy.rent();
}
核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个实现类,代理的是接口!
我们来使用动态代理实现代理我们之前写的UserService!
我们也可以编写一个通用的动态代理实现的类!所有的代理对象设置为Object即可!
package com.edgar.demo03;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 等会我们会用这个类,自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
// 被代理的接口
private Object target;
public void setTarget(Object target) {
this.target = target;
}
// 生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
this.target.getClass().getInterfaces(),this);
}
// 处理代理实例,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的本质,就是使用反射机制实现!
this.log(method.getName());
Object result = method.invoke(this.target, args);
return result;
}
public void log(String methodName){
System.out.println("执行了"+methodName+"方法");
}
}
测试!
package com.edgar.demo03;
import com.edgar.demo02.UserService;
import com.edgar.demo02.UserServiceImpl;
public class Client {
public static void main(String[] args) {
// 真实角色
UserService userService = new UserServiceImpl();
// 代理实例的调用程序
ProxyInvocationHandler pih = new ProxyInvocationHandler();
// 将真实角色放置进去
pih.setTarget(userService);
// 动态生成代理类
UserService proxy = (UserService) pih.getProxy();
proxy.delete();
}
}
测试,增删改查,查看结果!
动态代理的好处
静态代理有的它都有,静态代理没有的,它也有!
原文:https://www.cnblogs.com/edgarstudy/p/14999137.html