说动态代理之前,先说一下spring对事物的管理。我们都知道Spring有两大概念,即IOC(控制反转)和AOP(面向切面编程),spring就是利用AOP的原理来实现对事物的管理,而AOP又是使用了动态代理,那具体是怎么做的呢?简单说明一下:
在未使用框架之前,比如使用JDBC阶段,每次使对象入库做save操作的时候,我们都需要手动的去打开连接,提交事物,关闭连接,一万次save操作,就要打开一万次连接,提交一万次事物,关闭一万次连接。我们就想着抽取一些共性来,将相同的操作提取出来做一些优化,相同的操作是什么?打开连接、关闭连接,这两步是一样的,对于执行保存操作的方法肯定每次存取的值不同,不能够抽取。那与动态代理有什么关联呢?动态代理一个作用就是实现对某个方法的增强,而这个方法就是save方法,我们只需要创建一个代理,让代理每次遇到save方法的时候,就将抽取出来的打开连接、关闭连接的操作应用到save方法上,就简单很多,不用自己去手动控制了,”动态“,是指程序在运行时。
文章中用到的名词解释:被代理类和代理类的关系,类似于淘宝商家把货物委托到淘宝平台去销售
被代理类:淘宝的商家
代理类:相当于“淘宝”的角色
处理程序:委托的整个流程
一、正文开始,首先我们需要创建一个统一的接口——人,正常人都需要工作,这是人的共性
package com.sinosoft.test;
public interface Person {
void work();
}
二、程序员也需要工作,工作内容就比如是将数据入库,他实现了Person的接口
package com.sinosoft.test;
/**
* 被代理的类
*/
public class ITMan implements Person {
@Override
public void work() {
System.out.println("保存数据入库");
}
}
三、处理程序Handler类,里面有一个invoke方法,可以在执行保存操作之前自动打开数据库连接,执行完保存操作以后自动关闭数据库连接
package com.sinosoft.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
*请求处理类,相当于代理类要执行“被代理类所实现接口中的方法”
*就要先调用这个处理类中的处理程序
*/
public class MyHandler implements InvocationHandler {
public Object obj;//定义“被代理类”的引用
public MyHandler(Object obj){
this.obj=obj;
}
/**
* 代理类调用了某个方法,就会来调用这个处理程序,就是下面的invoke方法,
* 第一个参数基本不用,第二个参数是传过来的方法,第三个参数是传过来方法的参数数组
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
//反射:相当于执行“被代理类”的method方法--即传过来的work方法
method.invoke(obj, args);
after();
return null;
}
public void before(){
System.out.println("打开数据库的连接");
}
public void after(){
System.out.println("关闭数据库的连接");
}
/**
*每个代理类都要有一个与之关联的InvocationHandler,因为代理类本身并不处理方法,
*而是交给它的handler去处理它的invoke方法
*/
}
四、测试类, 目的是创建代理对象,让代理对象去执行被代理对象的方法,实现每次入库前自动打开连接,入库以后自动关闭连接。详细解释都在代码注释里面。
package com.sinosoft.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/***
* 动态代理:目的是实现方法的增强
* 创建代理类的步骤:
* 1、创建”被代理类“的对象
* 2、调用处理程序类即Handler类的构造,来创建InvocationHandler对象
* 3、使用java提供的proxy类的newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler handler)方法来创建代理类对象
*
*/
public class TestProxy {
public static void main(String[] args) {
//创建“被代理类”的对象,需要代理谁,就创建谁
ITMan man = new ITMan();
//InvocationHandler是代理对象的“调用处理程序”的入口
InvocationHandler handler = new MyHandler(man);
/**
* 生成一个代理对象,这个对象即不是ITMan的实例,也不是MyHandler的实例,它是运行期间动态生成的那个实例,这个实例
* 实现了被代理类实现的接口--即ITMan.class.getInterfaces(),也就是实现了person接口,所以根据多态转换成了
* Person接口类型
*/
//参数说明:(定义代理类的类加载器,代理类要实现的接口列表,指派方法调用的调用处理程序)
Person proxy=(Person)Proxy.newProxyInstance(TestProxy.class.getClassLoader(), ITMan.class.getInterfaces(), handler);
//让代理类去调用handler的处理程序,即invoke
proxy.work();
}
/**
* 当我们需要创建一个代理对象的时候,就使用它的newProxyInstance()方法,改方法主要是完成了两件事情,首先是动态的创建了一个类,然后生成该类的实例
* 创建完这个类,首先首先得加载到内存里面去,就是用这个类加载器完成的
*/
}