动态代理:
动态代理是指,程序在整个运行过程中根本就不存在目标类的代理类,目标对象的代理对象只是由代理生成工具(如代理工厂类)在程序运行时由jvm根据反射等机制动态生成的。代理对象与目标对象的代理关系在程序运行时才确立。
对比静态代理,静态代理是指在程序运行前就已经定义好了目标类的代理类。代理类与目标类的代理关系在程序运行之前就确立了
1、动态代理的概念
动态代理类似于普通当事人与聘请的律师之间的关系。律师是在“官司”发生后,才由当事人聘请的,即代理关系是在“官司”发生后才确立的。
动态代理的实现方式常用的有两种:使用JDK和Proxy,与通过CGLIB生成代理
通过JDK的java.lang.reflect.Proxy类实现动态代理,会使用其静态方法newProxyInstance(),依据目标对象、业务接口及业务增强逻辑三者,自动生成一个动态代理对象。
InvocationHandler是个接口,具体介绍如下:
实现了InvocationHandler的接口类用于加强目标类的主业务逻辑,这个接口中有一个方法invoke(),具体加强的代码逻辑就是定义在该方法中的,程序调用主业务逻辑时,会自动调用invoke()方法。
invoke方法的介绍如下:
由于该方法是由代理对象自动调用的,所以这三个参数的值不用程序员给出
第二个参数为Method类的对象,该类有一个方法也叫invoke(),可以调用目标类的目标对象,这两个invoke()方法,虽然同名,但是无关。
该方法的作用是:调用obj对象所属类的方法,这个方法由其调用者Method对象确定
在代码中,一般的写法为
method.invoke(target,args);
其中,method为上一层invoke方法的第二个参数,这样,即可调用了目标累的目标方法
2.JDK动态代理实现与解析
动态代理实现转账:
(1.)定义业务接口IAccountService,其中含有抽象方法transfer();
public interface IAccountService {
//主业务逻辑,转账
void transfer();
}
(2.)定义目标类IAccountServiceImpl,该类实现了业务接口,在对接口方法的实现上,只实现主业务逻辑转账即可,这个方法称为目标方法
public class IAccountServiceImpl implements IAccountService{
/**
* 目标方法
*/
public void transfer() {
System.out.println("调用Dao层,完成转账主业务");
}
}
(3.)定义主业务增强逻辑类MyExtension,该类需实现接口InvocationHandler。在该类中定义一个Object类型的成员变量,还要定义一个带参的构造器,这个参数为Object对象。目的是,将目标对象引入该类,以便通过反射调用目标方法。
当然,也可以将这个属性定义为IAccountService接口类型,但是最好不要这样做,最好将其定义为Object,因为这样这个主业务增强逻辑可以适用于本项目你的任何类型的目标类,而不仅仅拘泥于某一个类。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyExtension implements InvocationHandler {
//定义一个Object类型的变量
private Object target;
public MyExtension(){}
public MyExtension(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//增强主业务逻辑代码
System.out.println("对转账用户进项身份验证");
//无论主业务方法有误参数,有误返回值,下面的写法均可兼顾到
return method.invoke(target,args);
}
}
(4.)定义客户类client,客户类中主要语句有三句:
1.定义目标对象。在生成代理对象时会需要目标对象对其初始化
2.定义代理对象。需要注意的是,代理对象会通过反射机制,自动实现IAccountService接口。
代理对象需要使用目标对象对其进行初始化。
3.代理对象调用主业务方法。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class test {
public static void main(String[] args) {
//定义目标对象
IAccountService target = new IAccountServiceImpl();
//创建代理对象,并使用目标对象初始化它
IAccountService service = (IAccountService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),//获取目标对象的类加载器
target.getClass().getInterfaces(),//获取目标类的实现的所有接口
new MyExtension(target));//增强业务逻辑
//此时执行内容,就是对目标对象增加的内容
service.transfer();
}
}