上篇文章讲解了什么是静态代理,但是静态代理有一个问题就是需要建立很多的代理类,这样我们需要修改代理的方法的时候,需要在每个类中都要修改,这对于我们来说:当代理类很多的时候工作量就会成倍的增加。

于是针对上述问题,人们就提出了解决方案,我们在运行中来实现代理类的创建,也就是今天要讲解的主题——动态代理,首先先说的是JDK自带的动态代理的实现。

JDK自带的代理实现中最重要的两个内容:一是Proxy类,另一个是InvocationHandler接口。这两个是实现动态代理必须要用到的类和接口。

1)对于InvocationHandler接口,API给出了这样的定义:

     InvocationHandler 是代理实例的调用处理程序 实现的接口。

每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,

将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法

         Object invoke(Object proxy,
Method method,
Object[] args)
throws Throwable

proxy:指代理的那个真实对象

method:指调用真是对象的某个方法Method对象

args:指调用真实对象某个方法时接受的参数

2)Proxy类:

提供用于创建动态代理类和实例的静态方法,它还是由newProxyInstance方法创建的所有动态代理类的超类。

         public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException

loader:定义代理类的类加载器

interface:代理类要实现的接口列表

h:指派方法调用处理程序

返回值:一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口

也就是(返回一个由类加载器指定的代理类,它具有代理类Proxy中方法)这是我个人的理解

以上已经对于JDK中用到的内容进行了简单的了解,接下来我们来看如何在代码中实现动态代理,

1、定义一个接口

public interface Hello {
void say(String name);
}

2、定义一个类来实现这个接口,这个类就是我们的真实对象,HelloImpl

public class HelloImpl implements Hello {
@Override
public void say(String name) { System.out.println("Hello!"+name);
} }

3、定义一个动态代理,每个动态代理类都必须实现InvocationHandler这个接口

public class DynamicProxy implements InvocationHandler {
private Object target; public DynamicProxy(Object target){
this.target=target;
} @SuppressWarnings("unchecked")
public <T> T getProxy(){
return (T) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result =method.invoke(target,args);
after();
return result;
} private void before(){
System.out.println("Before");
} private void after(){
System.out.println("After");
}
}

4、接下来就是在客户端调用

public class Test {

    public static void main(String[] args){
Hello hello =new HelloImpl(); DynamicProxy dynamicProxy = new DynamicProxy(hello); Hello helloProxy=(Hello) Proxy.newProxyInstance(
hello.getClass().getClassLoader(),
hello.getClass().getInterfaces(),
dynamicProxy
);
helloProxy.say("Jack"); }
}

问题:由于上述在客户端调用过程中,每次动态创建代理类都会使用newProxyInstance这个方法,我们对其进行一层封装,如下:

1、封装一个类,HelloProxy

public class HelloProxy implements Hello {
private Hello hello; public HelloProxy(){
hello=new HelloImpl();
} @Override
public void say(String name) {
before();
hello.say(name);
after();
} private void before(){
System.out.println("Before");
} private void after(){
System.out.println("After");
}
}

2、客户端调用

public class Test {

    public static void main(String[] args){

        DynamicProxy dynamicProxy=new DynamicProxy(new HelloImpl());
Hello helloProxy =dynamicProxy.getProxy();
helloProxy.say("Jack"); }
}

Java动态代理-JDK自带实现的更多相关文章

  1. java 动态代理示例,带主要注释

    Java proxy是基于反射,仅仅支持基于接口的动态代理. java 动态代理是一切架构的基础,必须了解. 废话少说,先上代码获得感性认识. 示例代码有主要注释. 接口: public interf ...

  2. Java动态代理 ----- jdk代理与cglib代理

    1.jdk代理 针对接口进行代理,接口可以没有方法, InvocationHandler会拦截所有方法,不过好像意义不大....只能执行Object类的方法,执行结果有点奇怪... package t ...

  3. [转]java动态代理(JDK和cglib)

    转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html java动态代理(JDK和cglib) JAVA的动态代理 代理模式 代理 ...

  4. java动态代理(JDK和cglib)

    转:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代 ...

  5. 《转》JAVA动态代理(JDK和CGLIB)

    该文章转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的 ...

  6. 《转》java动态代理(JDK和cglib)

    该文章转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的 ...

  7. java动态代理(JDK和cglib实现对比)

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt214 JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特 ...

  8. Spring学习(四)—— java动态代理(JDK和cglib)

    JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他 的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托 ...

  9. java 静态代理 JDK动态代理 Cglib动态代理

    下面以一个简单的银行账户为例讲述讲述动态代理. 设计一个银行账户类,包含用户的账户余额,实现查询和更新余额功能 这个系统用了一段时间,有客户要求对账说账户余额给弄错了?因为上面没有存取款记录,最后银行 ...

随机推荐

  1. Azure容器监控部署(下)

    上文已经基本完成了环境的搭建,prometheus可以以https的方式从node_exporter和cAdvisor上pull到数据,访问grafana时也可以以https的方式访问,安全性得到了一 ...

  2. AI保存文件出现了未知错误 (Adobe Illustrator)

    可能的原因如下:1 把文件中所有的文字全选,转成曲线,把所有的文字都创建成轮廓2 新建一个页面,把制作的复制到新页面里3 需要把图层全部解锁再保存4 没有权限,设置一下即可5 PRINT SPOOLE ...

  3. 【Activiti学习之六】BPMN任务

    环境 JDK 1.8 MySQL 5.6 Tomcat 7 Eclipse-Luna activiti 6.0 一.任务任务表示流程中将要完成的工作. 1.任务继承 2.任务类型Service Tas ...

  4. 三个基于.net的浏览器内核使用的比较

    最近做模拟登陆发帖相关的项目 分别尝试了基于IE .NET自带的 webbrowser 和 基于WebKit 的WebKit.NET和openWebkitSharp 最开始肯定是用的.NET自带的we ...

  5. Prometheus + Consul 自动发现服务监控

    一.Prometheus支持的多种服务发现机制(常用如下) static_configs: 静态服务发现 file_sd_configs: 文件服务发现 dns_sd_configs: DNS 服务发 ...

  6. Storm里面fieldsGrouping和Field参数和 declareOutputFields

    Fields,个人理解,类似于一张表,你取那些字段以及这些字段所对应的数据给后面的bolt用 这个Field通常和fieldsGrouping分组机制一起使用,这个Field特别难理解,我自己也是在网 ...

  7. 14. Scala使用递归的方式去思考,去编程

    14.1 基本介绍 -Scala饰运行在Java虚拟机(Java Virtual Machine)之上,因此具有如下特点 1) 轻松实现和丰富的Java类库互联互通 2) 它既支持面向对象的编程方式, ...

  8. sqlalchemy 配合bootstrap-table实现后台分页

    创建公共的mysql连接函数 def db_session(): db_config='mysql+mysqldb://'+ mysqluser + ':' + mysqlpassword+'@'+m ...

  9. Mysql系列(四) —— MySQL的Charset和Collation

    本文转载自:再见乱码:5分钟读懂MySQL字符集设置 一.内容概述 在MySQL的使用过程中,了解字符集.字符序的概念,以及不同设置对数据存储.比较的影响非常重要.不少同学在日常工作中遇到的" ...

  10. SpringBoot中使用@scheduled定时执行任务需要注意的坑

    spring boot: 计划任务@ EnableScheduling和@Scheduled @Scheduled中的参数说明 @Scheduled(fixedRate=2000):上一次开始执行时间 ...