Proxy动态代理模式:
动态代理在Java中有JDK动态代理和CGLIB动态代理,也就是在运行中动态生成字节码并加载到虚拟机中供我们后续使用。
下面我们先看下这两种方式的区别。两者区别:
JDK动态代理:需要被代理对象的类实现了某些接口,生成的代理类也会实现相应的接口
CGLIB动态代理:不需要被代理对象的类实现了某些接口,生成的代理类为目标对象的类的子类
JDK动态代理:
下面我们对JDK动态代理进行解析:
1、java.lang.reflect.Proxy:根据InvocationHandler和目标类的类加载器,实现的接口生成代理类,生成的代理类也实现了这些接口,且使用相同的类加载器加载,然后再反射生成代理类的实例,反射生成的过程中会将InvocationHandler传递给父类的构造方法,因此实例化的代理类对象会持有InvocationHandler的引用
2、InvocationHandler:包含具体的被代理对象的引用,也代码中也就是target字段,根据invoke方法执行相应的操作
3、最终生成的代理类会继承Proxy类并实现UserService接口
创建UserService接口并定义一个抽象方法:
public interface UserService {
public String say(String name);
}
创建一个目标类UserServiceImpl:
public class UserServiceImpl implements UserService {
public String say(String name) {
System.out.println("I am UserServiceImpl,name is"+name);
return name;
}
}
利用反射来创建动态代理类MyProxy:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 动态代理类
* 作用:动态生成一个代理类
* 根据传过来的一个目标类生成一个代理类
*/
public class MyProxy implements InvocationHandler {
//定义目标类,用于创建生成的代理类,并调用目标方法
private Object object;
public MyProxy(Object o) {
this.object = o;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//代理类中通过反射调用(运行)目标类中的方法
System.out.println("已创建代理类");
Object invoke = method.invoke(object, args);
// System.out.println(invoke);
return invoke;
}
}
创建一个运行的类Demo:
import java.lang.reflect.Proxy;
public class Demo {
public static void main(String[] args) {
//普通方式直接调用目标类中的方法
// UserService userService=new UserServiceImpl();
// userService.say();
//生成代理类的$Proxy0.class文件
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
//利用动态代理生成的代理类调用目标类中的方法
UserService userService = new UserServiceImpl();
MyProxy myProxy=new MyProxy(userService);
//利用动态代理实现调用,最后生成一个代理类o,
//通过调用代理类中的方法去实现目标类的方法
//newProxyInstanc中的参数:
//1.任意的ClassLoader
//2.一个集合,interfence要代理的目标接口
//3.实现InvocationHandler的接口,代理类的对象myProxy
UserService o = (UserService)Proxy.newProxyInstance(Demo.class.getClassLoader(), new Class[]{UserService.class}, myProxy);
String say = o.say("张三");
// System.out.println(say);
}
}
运行结果:
JDK动态代理原理图: