JDK动态代理

 

1 什么是JDK动态代理

刚刚写ItcastConnection时爽么?因为Connection中的方法太多了,每个都要写,所以很累吧。累点到是没什么,可以完成功能就是好的。但是不是什么时候可以用代理的,有时你可能会遇到要代理的东西,只有在运行时才能知道,所以你不可能先把代理写出来!这时就需要使用动态代理。

JDK动态代理是JavaSE中一个高级特性,不是那么好理解的,但是它可是框架们的"秘密武器"。你要是可以理解它,那么将来在学习框架时,你就会知道框架是怎么完成一些"神奇功能"的。

 

动态代理的作用:在运行时生成一个实现了指定接口的对象。

  例如在运行时生成一个对象,这个对象实现了Connection接口。

 

2 JDK动态代理之Hello World

我们要写一个程序,这个程序会在运行时动态的生成一个对象,这个对象会实现Connection接口。

Connectoin c = (Connection)Proxy.newInstance(Connetion.class);

上面代码只是示意代码,不能编译通过的。

上面代码有个问题:生成一个实现了指定接口的对象,但是我们知道实现接口,需要为接口中每个方法添加实现内容,那么这个动态代理对象它是怎么实现Connection接口中的方法的呢?也就是说,我现在如果调用了代理对象的close()方法,它会执行什么呢?这就是问题!

想生成代理对象,还需要提供实现内容!

别的先别去管,先来看一个接口:InvocationHandler。

class HelloWorldHandler implements InvocationHandler {

    public Object invoke(Object proxy, Method method, Object[] args)

            throws Throwable {

        System.out.println("Hello 动态代理!");

        return
null;

    }

}

 

InvoactionHandler接口只有一个方法,invoke()!方法的参数你不要去管是什么意思,只需要知道它只有一个方法,名字叫invoke(),一会儿再去讨论它参数的含义。

  Connectoin c = (Connection)Proxy.newInstance(Connetion.class, new HelloWorldHandler());

  上面代码还是示意代码,不能编译通过。

我们这回在创建代理对象时,多给出了一个参数,是一个接口的实现类。实现类中有一条输出语句"Hello 动态代理!",现在生成的代理对象是Connection接口的实现类对象,你调用代理对象的任何方法都会调用HelloWorldHandler的invoke()方法,即输出"Hello 动态代理!"。

Connectoin c = (Connection)Proxy.newInstance(Connetion.class, new HelloWorldHandler());

c.close();

c.toString();

c.createStatement();

还是示意代码!

上面示意代码中调用了三个方法,无论哪个方法都会输出"Hello 动态代理!"。现在你知道InvocationHandler接口的作用了吧。

    public
void fun2() throws SQLException {

        ClassLoader loader = Thread.currentThread().getContextClassLoader();

        Class[] interfaces = {Connection.class};

        InvocationHandler h = new HelloWorldHandler();

        Connection con = (Connection)Proxy.newProxyInstance(loader, interfaces, h);

        con.close();

        con.toString();

        con.createStatement();

    }

 

3 真正的代理

虽然我们学会了动态代理,但还没有真正的代理。真正的代理是需要一个真正的连接对象,然后我们的代理对象使用它来完成任务。为了说明这个真正的代理,需要写几个类:

public
interface Waiter {

    public
void serve();

}

public
class WaiterImpl implements Waiter {

    public
void serve() {

        System.out.println("服务...");

    }

}

 

上面代码中写了一个Waiter接口,和一个WaiterImpl,它是Waiter接口的实现类。现在我们要写一个WaiterImpl的代理类。

public
class WaiterProxy implements Waiter {

    private Waiter waiter;

    public WaiterProxy(Waiter waiter) {

        this.waiter = waiter;

    }

    public
void serve() {

        waiter.serve();

    }

}

 

上面代理中,WaiterProxy就是一个代理类,当然,这个代理类没有实际的意义,因为它没有做任何的改变,所以没有意思!通常代理类是这样的,它会去实现一个接口,但它还需要一个该接口的实现类对象,然后所有实现都使用这个对象来完成。象是上面的代理中,WaiterProxy是一个代理类,它实现了Waiter接口,而且它还需要一个Waiter类型的对象,然后所有的实现都是代理这个对象功能。但是通常代理类会对被代理的对象的一些行为做一些改动,我们的例子中没有做。

 

上面的WaiterProxy虽然是一个代理类,但它不是动态代理。下面是通过JDK动态代理来生成一个代理对象。

public
class WaiterHandler implements InvocationHandler {

    private Waiter waiter;

    public WaiterHandler(Waiter waiter) {

        this.waiter = waiter;

    }

    public Object invoke(Object proxy, Method method, Object[] args)

            throws Throwable {

        return method.invoke(waiter, args);

    }

}

 

        ClassLoader loader = Thread.currentThread().getContextClassLoader();

        Class[] interfaces = {Waiter.class};

        Waiter watier = new WaiterImpl();

        InvocationHandler h = new WaiterHandler(watier);

        Waiter proxy = (Waiter)Proxy.newProxyInstance(loader, interfaces, h);

        proxy.serve();

 

4 使用动态代理完成连接池

public
class ItcastDataSource implements DataSource {

    private String username;

    private String password;

    private String url;

    private String driverClassName;

    

    private List<Connection> list = new ArrayList<Connection>();

    private
boolean
flag = true;

 

    private
void init() throws SQLException {

        flag = false;

        try {

            Class.forName(driverClassName);

        } catch(ClassNotFoundException e) {

            throw
new RuntimeException(e);

        }

        for(int i = 0; i < 5; i++) {

            final Connection con = DriverManager.getConnection(url, username, password);

            ClassLoader l = Thread.currentThread().getContextClassLoader();

            Class[] ins = {Connection.class};

            InvocationHandler h = new InvocationHandler() {

                public Object invoke(Object proxy, Method method, Object[] args)

                        throws Throwable {

                    if(method.getName().equals("close")) {

                        list.add((Connection)proxy);

                        return
null;

                    } else {

                        return method.invoke(con, args);

                    }

                }

            };

            Connection proxy = (Connection)Proxy.newProxyInstance(l, ins, h);

            list.add(proxy);

        }

    }

    

    public Connection getConnection() throws SQLException {

        if(flag) {

            init();

        }

        if(list.size() > 0) {

            return
list.remove(0);

        }

        throw
new RuntimeException();

    }

......

}

 

JDK动态代理连接池的更多相关文章

  1. Spring AOP详解 、 JDK动态代理、CGLib动态代理

    AOP是Aspect Oriented Programing的简称,面向切面编程.AOP适合于那些具有横切逻辑的应用:如性能监测,访问控制,事务管理以及日志记录.AOP将这些分散在各个业务逻辑中的代码 ...

  2. 【转载】Spring AOP详解 、 JDK动态代理、CGLib动态代理

    Spring AOP详解 . JDK动态代理.CGLib动态代理  原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspec ...

  3. 【原创】分布式之缓存击穿 【原创】自己动手实现静态资源服务器 【原创】自己动手实现JDK动态代理

    [原创]分布式之缓存击穿   什么是缓存击穿 在谈论缓存击穿之前,我们先来回忆下从缓存中加载数据的逻辑,如下图所示 因此,如果黑客每次故意查询一个在缓存内必然不存在的数据,导致每次请求都要去存储层去查 ...

  4. Spring AOP JDK动态代理与CGLib动态代理区别

    静态代理与动态代理 静态代理 代理模式 (1)代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理. (2)静态代理由 业务实现类.业务代理类 两部分 ...

  5. JDK动态代理与CGLib动态代理

    1.JDK动态代理 JDK1.3以后java提供了动态代理技术,允许开发者在运行期创建接口的代理实例,动态代理是实现AOP的绝好底层技术. JDK的动态代理主要涉及到java.lang.reflect ...

  6. JDK动态代理[4]----ProxyGenerator生成代理类的字节码文件解析

    通过前面几篇的分析,我们知道代理类是通过Proxy类的ProxyClassFactory工厂生成的,这个工厂类会去调用ProxyGenerator类的generateProxyClass()方法来生成 ...

  7. 017 Java中的静态代理、JDK动态代理、cglib动态代理

    一.静态代理 代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理. 静态代理由业务实现类.业务代理类两部分组成.业务实现类负责实现主要的业务方法,业 ...

  8. JDK动态代理深入理解分析并手写简易JDK动态代理(下)

    原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-05/27.html 作者:夜月归途 出处:http://www.guitu ...

  9. JDK动态代理深入理解分析并手写简易JDK动态代理(上)

    原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-03/27.html 作者:夜月归途 出处:http://www.guitu ...

随机推荐

  1. Windows 用VS编译libevent源码

    原理:从github上克隆libevent源码,然后使用cmake生成VS工程 github 上 libevent项目地址:https://github.com/libevent/libevent 第 ...

  2. How to use Variables in different component

    1. In Script Task component Set Value: Dts.Variables["ErrorMsg"].Value = string.Format(&qu ...

  3. Linux非阻塞IO(四)非阻塞IO中connect的实现

    我们为客户端的编写再做一些工作. 这次我们使用非阻塞IO实现connect函数. int connect(int sockfd, const struct sockaddr *addr, sockle ...

  4. 小结:VB.NET机房收费系统个人版

    经过几天的缝缝补补,自己的个人版最终OK了,!或许是由于有第一次的机房收费系统的经验,这次做,感觉很亲切. 在业务逻辑方面,沿袭曾经的逻辑.做了一点升级.可是修改不大. 在数据库方面,感觉自己从一个小 ...

  5. react-native Image resizeMode

    resizeMode (默认为 cover)该属性用来设置图片的缩放模式,对应值如下 cover 保持图片宽高比,直到宽度和高度都大于等于容器视图的尺寸(参考下图效果)contain 在保持图片宽高比 ...

  6. mobx 小结

    1.@observable 是一种让数据的变化可以被观察的方法 //@observable data 注册一个数据,这个数据将会成为一个可mobx监测的数据 2.decorator 修饰器只能修饰 类 ...

  7. excel表格快捷键

    CTRL+A   全选     CTRL+B   加粗       CTRL+C   复制      CTRL+D   下拉(复制上一个单元格的格式和内容)    CTRL+G   定位 CTRL+F ...

  8. IDEA下配置Spring Boot的热部署

    © 版权声明:本文为博主原创文章,转载请注明出处 devtools简介 spring-boot-devtools会监听classpath下的文件变动,并且会立即重启应用(发生在保存时机),因为其采用的 ...

  9. java数字签名算法之RSA

    © 版权声明:本文为博主原创文章,转载请注明出处 实例 1.项目结构 2.pom.xml <project xmlns="http://maven.apache.org/POM/4.0 ...

  10. which 命令

    我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索:        which  查看可执行文件的位置.       whereis 查看文件的位置.         ...