前言
- 代理:顾名思义,一个对象无法完成的事情交给代理对象来做。或者反过来,一般事情交给代理对象完成,代理对象完不成的事情交给雇佣来干。代理是需要花费资源的。动态代理:动态指运行时,代理对象才会出场。
- 注意:使用固定的代理(静态代理)和根据实际业务选择合适的代理对象(动态代理),开销也是不一样的。动态代理用到了反射。
- 反射是什么?按照正常的逻辑,.java文件编译成.class文件,二进制字节流类加载变成类文件,接着链接,初始化,变成可执行文件,也就是正常运行的程序。但是在运行的时候突然决定某一段程序不合适,需要修改,那么java提供的修改的方法就是反射。动态代理就是想要修改正在运行的可执行文件。
- 叛逆的总是有意思的。那么动态代理也是很有意思的功能,会给程序带来很多变化,前提是你要会使用。
代理HashMap
public class DynamicProxyTest {
private static Logger logger = LoggerFactory.getLogger(DynamicProxyTest.class);
public static void main(String[] args) {
Map proxyInstance = (Map) Proxy.newProxyInstance(DynamicProxyTest.class.getClassLoader(),
new Class[] {Map.class},
new DynamicInvocation(new HashMap<>()));
proxyInstance.put("userName", "John");
Object userName = proxyInstance.get("userName");
logger.info("userName:{}", userName);
}
}
class DynamicInvocation implements InvocationHandler {
private static Logger logger = LoggerFactory.getLogger(DynamicInvocation.class);
private Map<String, String> target;
public DynamicInvocation(Map<String, String> target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
logger.info("执行方法:{}, 方法参数:{}", method, args);
return method.invoke(target, args);
}
}
-
下面是输出
image.png
- 分析一下jdk动态代理的流程:
1.动态代理的类继承InvocationHandler,重写invoke方法,invoke就是对代理类的方法处理,上面的处理是每次HashMap调用之前都会打印出方法名和方法参数;
2.可以看到DynamicInvocation对象有个target字段,是Map类型。对,它就是需要代理的对象,通过构造函数传入,看起来和decorate方法很像。但是动态代理的核心是反射。
3.创建一个代理实例,使用Proxy.newProxyInstance()方法,有三个参数:类加载器,接口类文件,动态代理对象。说下接口类文件:java中类加载器加载的二进制字节流有两种:类和接口。二进制字节流被类加载器加载之后就是Class<>文件。jdk动态代理要求被代理类必须要有接口,所以没有接口的类都不能使用jdk动态代理,但是可以使用cglib动态代理。
4.jdk动态代理的是对象,接口中定义的所有方法都会在invoke方法中路过。invoke的地位参考高速收费口,不管多少车,都要从我这走,不同的是invoke吃拿卡要。- proxyInstance,代理对象新鲜出炉,代码运行期间生成的。
为什么使用动态代理?
- 程序员的能力体现在什么地方?我认为是掌控。掌控代码的生成,编译,加载,执行。代码大部分的生命周期都在执行上面,那么对代码执行的控制就很重要了。
- 方法什么时候执行的?方法执行之前能不能加点东西,我能不能在方法执行之前改变它的参数?我能不能记录每次方法执行参数,它的返回值?Map每次put的执行时间等。动态代理给我们提供了一种在方法执行的时候修改操控代码的方式。
- java对象有自己的垃圾回收功能,但是理解一个Class文件中不同对象在内存中的存储区域,生命周期,特性也是很重要的。一个方法是dubbo接口,http接口还是和数据存储相关的dao层代码,特性是不同的,围绕这这些东西我们的代码也可以衍生出更多的变化,而不是永远的单纯的crud。
网友评论