Java动态代理总结
动态代理
动态代理就是在程序运行期间,直接通过反射生成一个代理对象,代理对象所属的类是不需要存在的。
1. JDK的基于接口的动态代理
API介绍
Proxy
类
-
使用JDK的动态代理的要求:目标对象必须实现了接口。
-
相关类:JDK的类
java.lang.reflect.Proxy
,提供了生成代理对象的方法 -
生成代理对象的方法:
Proxy.newProxyInstance(ClassLoader loader,Class[] interfaces, InvocationHandler h)
loader
:类加载器interfaces
:目标对象所实现的接口 字节码数组h
:用于写代理对象要做的事情,通常写成InvocationHandler
接口的匿名内部类,实现其invoke
方法
InvocationHandler
接口
- 接口只有一个方法:每次当代理对象被调用时,这个方法都会执行。在方法里通常写代理对象的行为
invoke(Object proxy, Method method, Object[] args)
- 方法的参数:
Object proxy
:最终生成的代理对象Method method
:用户在调用代理对象时,所执行的方法对象Object[] args
:用户在调用代理对象,执行方法时,所传递的实参
- 方法的返回值:
- 当用户调用的代理对象的方法后,得到的返回值
使用示例
核心代码
// 创建代理对象
Proxy.newProxyInstance(
targetObj.getClass().getClassLoader(), //目标对象使用什么类加载器,代理对象就使用什么类加载器
targetObj.getClass().getInterfaces(), // 目标类实现什么接口,代理类也实现什么接口
new InvocationHandler() { //调用处理器,用于协调代理对象和真实对象之间的对话
/**
* 外面的代理对象,执行什么方法,那么这个invoke方法都会被执行。
* @param proxy 代理对象
* @param method 外面用代理对象调用的方法对象
* @param args 调用方法用到的参数
* @return 真实对象的方法执行完毕的返回结果。
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//System.out.println("调用了invoke~!~");
//增强功能的代码
//使用反射的手段让方法执行
Object obj = method.invoke(targetObj , args);
//增强功能的代码
return obj;
}
}
);
2.cglib的基于子类的动态代理
API介绍
Enhancer
类
-
使用cglib的要求:
- 目标对象不需要有接口
- 目标类不能是final类
- 要增强的方法不能是final方法
-
相关类介绍:
- jar包:Spring框架已经把cglib包含进去了,所以只要导入
spring-context
即可 - 核心类:
org.springframework.cglib.proxy.Enhancer
,提供了生成代理对象的方法
- jar包:Spring框架已经把cglib包含进去了,所以只要导入
-
生成代理对象的方法:
Enhancer.create(Class superClass, Callback callback)
-
superClass
:目标对象的字节码 -
callback
:回调函数,用于写代理对象要做的事情,通常写成MethodInterceptor
的匿名内部类对象callback相当于jdk动态代理中的
InvocationHandler
-
MethodInterceptor
接口
- 接口只有一个方法:每次当代理对象被调用时,这个方法都会执行。在方法里通常写代理对象的行为
intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
- 方法的参数:
Object proxy
:最终生成的代理对象Method method
:用户在调用代理对象时,所执行的方法对象Object[] args
:用户在调用代理对象,执行方法时,所传递的实参MethodProxy methodProxy
:用户在调用代理对象时,所执行的方法的代理对象methodProxy.invokeSuper(proxy, args)
:调用目标对象的方法,性能更强
- 方法的返回值:
- 当用户调用的代理对象的方法后,得到的返回值
使用示例
核心代码
Enhancer.create(
Super.class, // 父类是谁
new MethodInterceptor() { // 方法拦截器,外面使用代理对象调用什么方法,下面的这个intercept都会执行
/**
* 外面使用代理对象执行方法,这个intercept都会执行
* @param o 代理对象
* @param method 方法对象
* @param objects 参数
* @param methodProxy 方法代理
* @return 把真实对象的方法执行结果返回出去
* @throws Throwable
*/
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//System.out.println("执行了intercept方法~!");
//在这里面让被代理对象的方法执行
//使用反射的手法来调用
Object result = method.invoke(targetObj, objects);
return result;
}
}
);