Java笔记--动态代理
Java动态代理
1.概念
代理:
有时我们并不想直接访问对象A,或者不能直接访问对象A。而是通过访问一个中间对象B,让中间对象B去访问A。这种方式就称为代理。
这里的对象A所属的类就为委托类,或者被代理类。
对象B所属的类就是代理类。
使用代理访问的优点:
1.隐藏了被代理类的实现代码。
2.解耦,不改变被代理类的代码的情况下做一些额外的处理。(强调的是不改变被代理类的代码)。
比如调用SP的时候总是要获取sp,最后还要commit()。或者数据库操作等。在增删改查的前后总有一些相同的冗余代码。
根据程序运行前代理类是否已经存在,可以把代理分成静态代理和动态代理
静态代理
代理类在成勋运行前就已经存在的代理方式称为静态代理。(由开发人员编写或者编译器生成代理类的方式都属于静态代理)
静态代理实例:
//被代理的类
class TobeProxyed {
public void m1();
public void m2();
public void m3();
}
//代理类
class Proxy() {
//被代理类的对象
public class TobeProxyed proxyed;
public Proxy(TobeProxyed proxyed) {
this.proxyed = proxyed;
}
//代理类直接调用被代理类的方法。并且屏蔽了被代理类的//m3方法
public void proxyMethod1() {
proxyed.m1();
}
public void proxyMethod2() {
proxyed.m2();
}
}
静态代理中代理类和被代理类经常继承同一个父类或者实现同一个接口。
动态代理
代理类在程序运行前不存在,运行时由程序动态生成的代理方式称为动态代理
静态代理没有什么意思。动态代理的方式更灵活多变也是更需要理解的代理方式。
Java提供了动态代理的实现。可以在运行时动态的生成代理类。这样做代理就有一个非常大的好处————可以方便对代理类的函数做统一或者特殊的处理。如记录所有函数执行时间,所有函数执行前添加验证判断,对某个特殊函数进行特殊操作。不用像静态代理那样修改所有的方法。用静态代理只需要改一处invoke方法。
动态代理的实例:
实现动态代理包括三步:
1.要有被代理类的实例
2.写一个实现InvocationHandler接口的类(这个类是连接代理类和被代理类的中间类必须实现的接口)
3.调用Proxy.newProxyInstance()方法创建代理类对象
现在加入我们想要实现统计某个类所有函数的执行时间。传统的静态代理方式是在类的每个函数前后调用统计方法。
假如有100个方法的话,就要把相同的代码写100次。这时候静态代理的方式就很麻烦。
此时如果使用动态代理的方式就会很简单。只需要写一遍统计代码就OK了。
动态代理实例:
被代理类和被代理类接口
//这是被代理类的接口
public interface ProxyedInterface {
public void proxyedM1();
public void proxyedM2();
public void proxyedM3();
}
//这是被代理类
public class ProxyedClassImpl implements ProxyedInterface {
@Override
public void proxyedM1() {
System.out.println("proxyedM1 invoked");
}
public void proxyedM2() {
System.out.println("proxyedM2 invoked");
}
public void proxyedM3() {
System.out.println("proxyedM3 invoked");
}
}
中间类实现InvocationHandler接口
有了要被代理的类。下面写一个中间类实现InvocationHandler接口的invoke方法。
//中间代理类
public class MiddleProxyClass implements InvocationHandler {
//被代理类的对象
private Object proxyedClassImpl
public MiddleProxyClass(Object proxyedClassImpl) {
this.proxyedClassImpl = proxyedClassImpl;
}
//调用被代理累的相应方法都会到调用这个方法内,在这里可以在方
//法的前后做相应的处理,但是无法改变被代理类的方法的内部逻辑
@Override
public Object (Object proxy, Method method, Object[] args) throws Throwable {
long start = System.currentTimeMillis();
Object o = method.invoke(proxyedClassImpl, args)//调用被代理累proxyedClassImpl的指定方法
System.out.println(method.getName() + " cost time : " + (System.currentTimeMillis()-start))
return o;
}
}
通过 Proxy 类静态函数生成代理对象
public class Main {
public static void main(String[] args) {
// create proxy instance
MiddleProxyClass middleProxyClass = new MiddleProxyClass(new ProxyedClassImpl());
//在这里动态生成实际的代理类对象 proxyedInterface
ProxyedInterface proxyedInterface = (ProxyedInterface)(Proxy.newProxyInstance(ProxyedInterface.class.getClassLoader(), new Class[] {ProxyedInterface.class},
middleProxyClass));
// call method of proxy instance
proxyedInterface.proxyedM1();
System.out.println();
proxyedInterface.proxyedM2();
System.out.println();
proxyedInterface.proxyedM3();
}
}
每次调用Proxy.newProxyInstance生成的代理类对象的方法,都会调用到中间类对象middleProxyClass的invoke方法。而invoke方法实现中会调用被代理类的指定方法。
生成代理类的静态方法: Proxy.newProxyInstance(…)
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
loader表示类加载器
interfaces表示委托类的接口,生成代理类时需要实现这些接口
h是InvocationHandler实现类对象,负责连接代理类和委托类的中间类
我们可以这样理解,如上的动态代理实现实际是双层的静态代理,开发者提供了委托类 B,程序动态生成了代理类 A。开发者还需要提供一个实现了InvocationHandler的子类 C,子类 C 连接代理类 A 和委托类 B,它是代理类 A 的委托类,委托类 B 的代理类。用户直接调用代理类 A 的对象,A 将调用转发给委托类 C,委托类 C 再将调用转发给它的委托类 B。
Java笔记--动态代理的更多相关文章
- 【设计模式】Java设计模式 - 动态代理
[设计模式]Java设计模式 - 动态代理 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 最近工作比较忙,没啥时间学习 目录 [设计模 ...
- java的动态代理机制详解
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
- java中动态代理实现机制
前言: 代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系 ...
- Java特性-动态代理
代理在开发中无处不在: 我们完成一个接口开发A,接口下有很多个实现类,这些类有些共同要处理的部分,比如每一个类都定义了接口A中的方法getXX(String name).我现在想把每次调用某个实现类的 ...
- java --- 设计模式 --- 动态代理
Java设计模式——动态代理 java提供了动态代理的对象,本文主要探究它的实现, 动态代理是AOP(面向切面编程, Aspect Oriented Programming)的基础实现方式, 动态代理 ...
- java的动态代理机制
前几天看到java的动态代理机制,不知道是啥玩意,然后看了看.死活不知道 invoke(Object proxy, Method m, Object[] args)种的proxy是个什么东西,放在这里 ...
- java中动态代理
一.在java中怎样实现动态代理 1.我们要有一个接口,还要有一个接口的实现类,而这个实现类呢就是我们要代理的对象 接口: package org.dynamicproxy.test; public ...
- Java的动态代理机制详解(转)
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
- (转)java的动态代理机制详解
原文出自:http://www.cnblogs.com/xiaoluo501395377/p/3383130.html 在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一 ...
随机推荐
- CodeForces 279C Ladder (RMQ + dp)
题意:给定一个序列,每次一个询问,问某个区间是不是先增再降的. 析:首先先取处理以 i 个数向左能延伸到哪个数,向右能到哪个数,然后每次用RQM来查找最大值,分别向两边延伸,是否是覆盖区间. 代码如下 ...
- InnoDB recovery过程解析
本文来自网易云社区. InnoDB如果发生意外宕机了,数据会丢么?对于这个问题,稍微了解一点MySQL知识的人,都会斩钉截铁的回答:不会!为什么?他们也会毫不犹豫的说:因为有重做日志(redo log ...
- OTRS 二次开发笔记
公司使用otrs系统处理业务工单,各种事件流.因为是开源免费系统,因此需要在上面做一些功能补充或定制的二次开发. otrs是什么? OTRS 是一个功能强大的工单系统.完美适用于服务台(Help De ...
- Java——利用集合类实现简单斗地主发牌
import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util ...
- [Cqoi2014]危桥 (两遍网络流)
题目链接 #include <bits/stdc++.h> using namespace std; typedef long long ll; inline int read() { , ...
- Unraveling the JPEG file
(文章还剩实践部分没写,答辩过后补上...) JPEG文件在当下数字化生活中是无处不在的,但是在熟悉的JPEG面纱背后,隐藏着一些算法,它们去除了人类眼中无法察觉到的细节.这产生了最高的视觉质量与最小 ...
- OpenLayers v4.2.0 -----地图延迟加载;
官方:http://openlayers.org/en/latest/examples/lazy-source.html <!DOCTYPE html> <html> < ...
- Helvetic Coding Contest 2016 online mirror B1
Description The zombies are gathering in their secret lair! Heidi will strike hard to destroy them o ...
- jquery uploadify在IE上传报406HttpError
前端使用uploadify的flash上传控件,后端使用spring MVC,使用IE上传时报406,用Chrome没有问题. 检查发现IE上传时的请求头中,Accept: text/* 而Chrom ...
- chapter06
/** * Created by EX-CHENZECHAO001 on 2018-03-30. */class Chapter06 { } // 6 对象// 用对象作为单例或存放工具的方法// 类 ...