`
gupeng_ie
  • 浏览: 25240 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

动态代理(附原理图)

阅读更多

代理:

代理主要体现在(代理类)和(委托类)之间的协调工作,

1.代理类 --proxy

承接着(委托类--目标类)的相关服务的(扩展处理--方法功能增强)的责任

分为 静态代理类 和 动态代理类。

 

*动态代理类:

利用java反射机制--Proxy类 和 InvocationHandler接口。 

 

首先创造一个 (接口实现) 和一个 (InvocationHandler)实例,

{以类装载器、接口数组(Class对象),InvocationHandler来生成}--> (代理类)。 

 

通过 代理类--Proxy 的代理,

(接口) 和 (实现类) 之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联。  

 

java.lang.reflect.Proxy只能代理(接口),不能代理类。

JDK提供的动态代理只适用于实现接口的类,

CGlib实现动态代理,它提供动态代理的对象可以不实现接口。

 

Java Proxy功能主要通过

java.lang.reflect.Proxy类 与

java.lang.reflect.InvocationHandler接口

实现。

 

*静态代理类:

在程序运行前,代理类的.class文件就已经存在。

 

2.委托类 --目标类

是接口的真正的实现者。 

------------------------------------------------------------------------------------------------

 

动态代理 代码详解:

* 使用程序自动的去完成方法的增强,使用程序去生成代理类

* 获得代理类,Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 

* 实现

Proxy.newProxyInstance(

ClassLoader,//确定代理类被加载到内存的类加载器,一般使用当前类的类加载器

Class[],    //确定代理类需要实现的接口的字节码

InvocationHandler //接口,具体的处理类,在此我们使用到匿名内部类

 //invoke(Object proxy,Method method,Object[] args) -->需要重写的方法

 //* proxy,代理对象本身--代理

 //* method,代理对象执行的方法 在内存的描述,即为一个反射对象

 //* args,当前方法执行的具体、实际参数

 

 //* invoke,委托类的每一个方法在执行时,将被invoke()拦截,即都会调用invoke()

)

 

**获得接口的两种方法:

  final Subject realSubject = new RealSubject();

realSubject.getClass().getInterfaces();

new Class[]{Subject.class};

------------------------------------------------------------------------------------------------

代理作用:

对 (目标对象)--委托类 访问时,对其方法进行拦截,我们可以在此,对我们需要的方法进行功能增强。

即 拦截、增强

 

-------------------------------------------------------------------------------------------------

实例--用 代理 完成连接池

* 思路:

* 1.通过DriverManager获得链接(mysql)

* 2.使用自定义代理类获得链接

* 通过程序编写实现类(动态代理)

* 代理对象的每一个方法都会执行InvocationHandler的invoke方法

* 对具体的方法做出处理,通过方法的名称进行判断。method.getName()

* 注意:需要进行返回return --> 跳出方法

* 对被代理对象--委托类(具体Connection的实现类),进行其他方法的执行。

* 反射:method.invoke(被代理对象--委托类,实际参数)

* 3.目的,对需要增强的方法进行增强

* 将close方法原有的内容替换成,"将当前链接归还给连接池"。

 

*连接池 工具类 代码:

package cn.gp.pool.utils;

 

import java.io.InputStream;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

import java.util.LinkedList;

import java.util.Properties;

 

public class PoolProxyUtils {

 

//创建 连接池--集合,用来盛放 连接--Connection

private static LinkedList<Connection> pool = new LinkedList<Connection>();

//初始化 连接,将 连接 放入 连接池,并使用 动态代理

static {

try {

//获得 建立连接 的参数

InputStream is = PoolProxyUtils.class.getClassLoader()

.getResourceAsStream("jdbc.properties");

 

Properties prop = new Properties();

prop.load(is);

 

String driver = prop.getProperty("driver");

String url = prop.getProperty("url");

String user = prop.getProperty("user");

String password = prop.getProperty("password");

 

//加载驱动

Class.forName(driver);

 

//建立连接池 **核心代码**

for (int x = 0; x < 10; x++) {

// 获得 连接对象--委托类

final Connection conn = DriverManager.getConnection(url, user,

password);

 

//创建 代理对象

Connection connctionProxy = (Connection) Proxy.newProxyInstance(

PoolProxyUtils.class.getClassLoader(), // 提供 类加载器

new Class[] { Connection.class }, // 提供 委托类接口

new InvocationHandler() { // 具体 处理类

 

@Override

public Object invoke(Object proxy,

Method method, Object[] args)

throws Throwable {

// 查看正在使用 委托类的哪个方法

String name = method.getName();

 

// 增强close方法

if ("close".equals(name)) {

// 将 连接 归还 连接池

pool.add((Connection) proxy);

// 跳出invoke()

return null;

}

 

// 其他方法 调用 原类 的方法

return method.invoke(conn, args);

}

});

// 将 代理类对象 添加到 连接池 中

pool.add(connctionProxy);

}

} catch (Exception e) {

throw new RuntimeException(e.getMessage(), e);

}

 

}

//获得连接

public static Connection getConnection() {

//如果 连接池 中有 连接,就获取

if (pool.size() > 0) {

return pool.get(0);

}

//连接池中没有 连接,稍等,递归,调用自身

try {

Thread.sleep(500);

} catch (Exception e) {

throw new RuntimeException(e.getMessage(), e);

}

return getConnection();

}

//释放资源

public static void closeResource(Connection conn, Statement st, ResultSet rs) {

try {

if (rs != null) {

rs.close();

}

} catch (SQLException e) {

e.printStackTrace();

} finally {

try {

if (st != null) {

st.close();

}

} catch (SQLException e) {

e.printStackTrace();

} finally {

try {

if (conn != null) {

conn.close();

}

} catch (SQLException e) {

e.printStackTrace();

}}}}}

-----------------------------------------------------------------------------------------------------------------------------


--------------------------------------------------------------------------------------------

**调用原理:

 

  • 大小: 49.1 KB
  • 大小: 53.2 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics