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

于是针对上述问题,人们就提出了解决方案,我们在运行中来实现代理类的创建,也就是今天要讲解的主题——动态代理,首先先说的是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. 微慕WordPress小程序增强版

    2017年1月9日,张小龙在2017微信公开课Pro上发布的微信小程序正式上线.在过去的2年多的时间里,微信小程序领头,各大互联网平台也不甘落后,陆续推出自己的小程序.2018年7月4日,百度智能小程 ...

  2. DDD框架基础知识

    DDD框架基础知识 参考: https://www.cnblogs.com/zhili/p/OnlineStorewithDDD.html(领域驱动设计,分层架构) https://www.cnblo ...

  3. 【C/C++开发】C++11 并发指南一(C++11 多线程初探)

    引言 C++11 自2011年发布以来已经快两年了,之前一直没怎么关注,直到最近几个月才看了一些 C++11 的新特性,今后几篇博客我都会写一些关于 C++11 的特性,算是记录一下自己学到的东西吧, ...

  4. Tomcat通过脚本自动部署

    1:autodeploy_tomcat_app.sh now=`date +%Y%m%d%H%M%S` tomcatPath=/home/test/apache-tomcat- backupPath= ...

  5. 重置mysql root密码

    首先结束mysql进程,利用ps aux | grep mysql命令得到进程ID号,kill ID号,结束进程其次,运行mysqld --skip-grant-tables 或者mysqld_saf ...

  6. UserAgentUtils 获取浏览器信息

    <dependency> <groupId>eu.bitwalker</groupId> <artifactId>UserAgentUtils</ ...

  7. Linux(二)各种实用命令

    继续Linux命令学习,没有什么捷径,每个命令都去敲几遍就熟悉了,第二篇学习的是一些比较实用类的命令,主要是从开发的角度进行学习,并不深入,话不多说,开始! 一.系统管理类 1.1 stat --st ...

  8. Spring项目中的数据库加密

    有时候为了安全,我们需要对数据库密码进行加密: SpringDruid数据源加密数据库密码 当我们初步开始打造系统时,什么都没有一片空白,而数据源使用的是SpringDruid时,我们可以通过这篇博客 ...

  9. 【开发笔记】-Tomcat启动时设置Jdk版本

    1. Window版本Tomcat 到bin下的setclasspath.bat文件,在文件的开始处添加如下代码: set JAVA_HOME=D:\Program Files\Java\jdk1.8 ...

  10. 从零搭建一个简单的webpack环境

    1.npm Init 2.创建webpack.config.js文件,并配置入口和出口 3.Package.json的script中配置命令对应的操作 .安装webpack-dev-server 模块 ...