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

于是针对上述问题,人们就提出了解决方案,我们在运行中来实现代理类的创建,也就是今天要讲解的主题——动态代理,首先先说的是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. Sql Server 数据库出现“可疑”的解决办法

    问题:数据库名称出现“可疑”字样 解决: 方法一: 重新还原数据库 方法二: 贴上语句:(DB_CS:你的数据库名) 第一步: ALTER DATABASE DB_CS SET EMERGENCY 第 ...

  2. gcd 题解

    gcd Little White learned the greatest common divisor, so she plan to solve a problem: given \(x, n,\ ...

  3. 第一周 coursera.org

    机器学习:定义一.给予计算机能自我学习的能力而不是编程.定义二.对于某类任务T和性能度量P,如果一个计算机程序在T上以P衡量的性能随着经验E而自我完善,那么我们称这个计算机程序在从经验E学习 监督学习 ...

  4. 032 搭建搜索微服务01----向ElasticSearch中导入数据--通过Feign实现微服务之间的相互调用

    1.创建搜索服务 创建module: Pom文件: <?xml version="1.0" encoding="UTF-8"?> <proje ...

  5. [转帖]如何获得一个RAC Oracle数据库(从Github - oracle/docker-images) - 本地版 ---暂时未做实验.

    如何获得一个RAC Oracle数据库(从Github - oracle/docker-images) - 本地版 2019-11-09 16:35:30 dingdingfish 阅读数 32更多 ...

  6. Django阅读目录

    (一)Django框架简介 (二)Django框架之第二篇--app注册.静态文件配置.form表单提交.pycharm连接数据库.django使用mysql数据库.表字段的增删改查.表数据的增删改查 ...

  7. cocos2d设置窗口标题

    //窗口标题 #ifdef WIN32 CCEGLView* pGlView=CCDirector::sharedDirector()->getOpenGLView(); if (pGlView ...

  8. 深入理解 Linux Cgroup 系列(一):基本概念

    原文链接:深入理解 Linux Cgroup 系列(一):基本概念 Cgroup 是 Linux kernel 的一项功能:它是在一个系统中运行的层级制进程组,你可对其进行资源分配(如 CPU 时间. ...

  9. Jquery源码解析及案例分析

    本人刚学先上链接(别人写的挺好的)后期同步补上

  10. python自动备份阿里云数据库binlog

    #coding:utf8from aliyunsdkcore import clientfrom aliyunsdkrds.request.v20140815 import DescribeBacku ...