java动态代理

介绍

Spring框架是目前开发中使用最广泛框架,spring的核心功能一个是ioc一个是aop.。Aop的核心功能就是使用java的动态代理,在许多框架中也使用了动态代理,目前在看mybatis源码,数据库连接池中,关闭connection连接中,是将connection放回了连接池,而不是调用了close()方法,这块就使用了动态代理的方式,我先介绍下动态代理的实现方式,后面介绍mybatis连接池在这块的使用。

java的动态代理主要涉及两个类一个接口类InvocationHandler ,一个代理类java.lang.reflect.Proxy

jdk源码

package java.lang.reflect;


public interface InvocationHandler {

/*proxy:实际的对象
*method:代理嗲用的方法
args: 方法参数
*/
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

动态代理实现

  1. 定义接口类
public interface HelloInterface {

    String sayHello(String msg);
}

  1. 定义实现类
public class HelloImpl implements  HelloInterface {

    @Override
    public String sayHello(String msg) {
        System.out.println("他说:"+msg);
        return msg;
    }
}

3 定义handler类

public class HeloProxy implements InvocationHandler {

    private static final Class<?>[] IFACES = new Class<?>[] { HelloInterface.class };
    private final HelloInterface helloInterface; // 被代理的类
    private final HelloInterface realInterface; // 实际的原始类

    public HeloProxy(HelloInterface helloInterface) {
        realInterface = helloInterface;
        this.helloInterface = (HelloInterface) Proxy.newProxyInstance(HelloInterface.class.getClassLoader(),IFACES,this);
        //生成代理类
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	//当通过helloInterface调用方法sayHello 是走的这里
        String name = method.getName();
        System.out.println("当前调用方法"+name);
        return  method.invoke(realInterface,args);

    }


    public HelloInterface getHelloInterface() {
        return helloInterface;
    }
}

4 main 方法

        HelloInterface helloInterface = new HelloImpl();
        HeloProxy heloProxy = new HeloProxy(helloInterface);
        String string = heloProxy.getHelloInterface().sayHello("动态代理");
        System.out.println(string);

输出结果:

当前调用方法sayHello
他说:动态代理
动态代理

Proxy类我们主要调用方法newProxyInstance方法,调用该方法生成代理类

// ClassLoader loader 被代理类的加载器
// interfaces 被代理类的interface
//InvocationHandler  实现该接口的方法类
 public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

mybaitis 应用

在mybatis中,为了减少与数据库的连接次数,减少消耗的性能,我们一般都使用连接池,再使用完connnection后不是关闭连接而是放入连接池中。从连接池取到connection就是被代理过的连接。

从连接池中获取连接的代码

public class PooledDataSource implements DataSource 
  @Override
  public Connection getConnection() throws SQLException {
    return popConnection(dataSource.getUsername(), dataSource.getPassword()).getProxyConnection();
    // 从这个可知我们从连接池中获取到的连接是被代理过的connection
  }

实现InvocationHandler 的类
class PooledConnection implements InvocationHandler

//构造器
  public PooledConnection(Connection connection, PooledDataSource dataSource) {
    this.hashCode = connection.hashCode();
    this.realConnection = connection;
    this.dataSource = dataSource;
    this.createdTimestamp = System.currentTimeMillis();
    this.lastUsedTimestamp = System.currentTimeMillis();
    this.valid = true;
    this.proxyConnection = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), IFACES, this);
    // 这个proxyConnection  就是上面的.getProxyConnection();
  }

// invoke方法
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    String methodName = method.getName();
    if (CLOSE.hashCode() == methodName.hashCode() && CLOSE.equals(methodName)) {
      //在这里我们得知,当connection调用close方法时,并没有真正调用close()方法,而是放入到了连接池中
      dataSource.pushConnection(this);
      return null;
    }
    try {
      if (!Object.class.equals(method.getDeclaringClass())) {
        // issue #579 toString() should never fail
        // throw an SQLException instead of a Runtime
        checkConnection();
      }
      return method.invoke(realConnection, args);
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }

  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值