基本介绍
- 代理对象不需要实现接口,但是目标对象要实现接口,否则不能使用JDK动态代理
- 代理对象的生成,时利用JDK的API,动态的在内存中构建代理对象
- 也叫JDK代理、接口代理
- 代理最主要原因就是不改变目标对象方法的情况下对方法进行增强
使用API
1.代理类所在包:java.lang.reflect.Proxy
2.JDK实现只需使用newProxyInstance方法,但是该方法需要接收三个参数
newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
使用
创建接口
public interface People {
public void say(String words);
public void run();
}
创建实现类
public class Student implements People {
@Override
public void say(String words) {
System.out.println("I will say " + words);
}
@Override
public void run() {
System.out.println("keep running!");
}
}
创建代理工厂
方式一
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author ZhangXiong
* @version v12.0.1
* @date 2020-06-16
*/
public class ProxyFactory implements InvocationHandler {
// 被代理对象
private Object target = null;
// 绑定代理对象
public Object bind(Object target){
this.target = target;
/**
* 传参
* 1.类加载器,采用target本身的类加载器
* 2.生成代理对象挂载在那些接口下
* 3.实现方法逻辑的代理类,this表当前对象,必须实现InvocationHandler接口的invoke方法
*/
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
// 代理方法逻辑的代理类
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入代理逻辑");
Object obj = method.invoke(target, args);
System.out.println("调度真实对象后的服务");
return obj;
}
}
方式二
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author ZhangXiong
* @version v12.0.1
* @date 2020-03-09
* 设计模式
* 代理模式 动态代理之利用JDK的反射的Proxy实现动态代理
* 代理对象,不需要实现接口,但是目标对象要实现接口,否则不能用动态代理
* 代理对象的生成,是利用 JDK 的 API,动态的在内存中构建代理对象
* 动态代理也叫做: JDK 代理、接口代理
* 代理类所在包:java.lang.reflect.Proxy
* JDK 实现代理只需要使用 newProxyInstance 方法,但是该方法需要接收三个参数,完整的写法是:
* static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
*/
public class ProxyFactory {
//维护一个目标对象 , Object
private Object target;
//构造器 , 对target 进行初始化
public ProxyFactory(Object target) {
this.target = target;
}
//给目标对象 生成一个代理对象
public Object getProxyInstance() {
//说明
/*
* public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
//1. ClassLoader loader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定
//2. Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型方法确认类型
//3. InvocationHandler h : 事情处理,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入
*/
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入代理逻辑");
//反射机制调用目标对象的方法
Object returnVal = method.invoke(target, args);
System.out.println("调度真实对象后的服务");
return returnVal;
}
});
}
}
使用代理
对应方式一的使用
public class JDKProxy {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory();
People proxy = (People)factory.bind(new Student());
proxy.run();
proxy.say("hello world!");
}
}
对应方式二的使用
public class JDKProxy {
public static void main(String[] args) {
//创建目标对象
People target = new Student();
//给目标对象,创建代理对象, 可以转成 ITeacherDao
People proxyInstance = (People)new ProxyFactory(target).getProxyInstance();
// proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象
System.out.println("proxyInstance=" + proxyInstance.getClass());
//通过代理对象,调用目标对象的方法
proxyInstance.run();
proxyInstance.say("hello world!");
}
}
结果
参考了尚硅谷韩顺平老师讲的设计模式以及《JavaEE互联网轻量级框架整合开发》一书