【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权)
https://blog.csdn.net/m0_69908381/article/details/129917996
出自【进步*于辰的博客】
前篇【关于对【java静态代理】的理解与简述(基于JDK1.8)】已经简述过什么是代理模式?什么是静态代理?
参考笔记一,P83;笔记二,P75.4。
动态代理指在不变动源代码(目标对象)的情况下,无需手动创建代理类,而是通过反射创建代理对象来实现代理功能的代理。
特点:面向接口,隶属于Java API。
看下述代码:
1、公共接口。
/**
* 公共接口,目标对象和代理对象的公共接口,
* 注:动态代理中代理对象是通过反射创建的(在JVN中,看不到),
* 因为JDK动态代理面向接口,故目标对象和代理对象实现于同一接口
*/
interface StudentService {
// 修改成绩
int changeScore(int score);
}
2、目标类。
class PrimaryStudent implements StudentService {
@Override
public int changeScore(int score) {
System.out.println("成绩加" + score + "分");
return 1;
}
}
3、事务类:用于附加功能。
class Transaction {
public void before() {
System.out.println("打开事务");
}
public void after() {
System.out.println("关闭事务");
}
}
4、代理类。
/**
* JDK动态代理类,需实现接口 InvocationHandler
*/
class DynamicProxy implements InvocationHandler {
private Object target;// 目标对象,无需指定具体目标类类型
private Transaction transaction;
public DynamicProxy(Object target, Transaction transaction) {
this.target = target;
this.transaction = transaction;
}
/**
* 代理时执行方法
*
* @param proxy 代理对象,暂未用到
* @param method 目标对象的 Method 的 class对象
* @param args 目标对象的 Method 的参数数组
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
transaction.before();
/**
* 解释:先看下面测试类内的 proxy.changeScore(15), 由于代理对象proxy实现于公共接口 CommonService,
* 故proxy也有 changeScore()。
* 当 proxy.changeScore(15) 时,就会执行当前invoke()。
*/
Object result = method.invoke(target, args);// 这就是反射中Method对象执行时的方法,即通过反射调用目标对象被代理的方法
transaction.after();
return result;
}
}
5、测试类。
class Test {
public static void main(String[] args) {
PrimaryStudent target = new PrimaryStudent();
Transaction transaction = new Transaction();
/**
* 创建代理对象(通过反射)
* 注:第一个参数是目标对象的类加载器,指定为哪个目标对象创建代理对象;
* 第二个参数是目标对象实现的接口,指定目标对象和代理对象的公共接口、
* 第三个参数是拦截器对象,指定用哪个拦截器来创建代理对象
* 注:由于代理对象proxy是通过反射创建于JVM,并无类存在,故要上转为公共接口 CommonService
*/
StudentService proxy = (StudentService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new DynamicProxy(target, transaction));
int x = proxy.changeScore(15);
if (x > 0)
System.out.println("成绩修改成功");
else
System.out.println("成绩修改出错");
}
}
测试结果:
newProxyInstance()用于创建代理对象,调用相应方法指调用重写的invoke()
,调用目标方法的本质是反射。
特点:面向继承,隶属于Spring API。
看下述代码:
1、目标类。
class PrimaryStudent {
public int changeScore(int score) {
System.out.println("成绩加" + score + "分");
return 1;
}
}
2、事务类:用于附加功能。
class Transaction {
public void before() {
System.out.println("打开事务");
}
public void after() {
System.out.println("关闭事务");
}
}
3、代理类。
/**
* Cglib动态代理类,需实现接口 MethodInterceptor
*/
class DynamicProxy implements MethodInterceptor {
private Object target;// 目标对象,无需指定具体目标类类型
private Transaction transaction;
public DynamicProxy(Object target, Transaction transaction) {
this.target = target;
this.transaction = transaction;
}
public Object createProxy() {
Enhancer proxy = new Enhancer();// 创建代理对象
proxy.setCallback(this);// 设置拦截器,指定回滚对象为自身
proxy.setSuperclass(target.getClass());// 设置父类,指定为哪个目标对象创建代理对象
return proxy.create();
}
/**
* 代理时执行方法
*
* @param o 未知参数
* @param method 目标对象的 Method 的 class对象
* @param args 目标对象的 Method 的参数数组
* @param methodProxy 未知参数
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
transaction.before();
Object result = method.invoke(target, args);
transaction.after();
return result;
}
}
4、测试类。
class Test {
public static void main(String[] args) {
PrimaryStudent target = new PrimaryStudent();
Transaction transaction = new Transaction();
/**
* 创建代理对象(通过反射)
* 注:由于代理对象proxy是通过反射创建于JVM,并无类存在。代理对象继承于目标对象,故将proxy上转为 PrimaryStudent
*/
PrimaryStudent proxy = (PrimaryStudent)new DynamicProxy(target, transaction).createProxy();
int x = proxy.changeScore(30);
if (x > 0)
System.out.println("成绩修改成功");
else
System.out.println("成绩修改出错");
}
}
测试结果:
createProxy()
返回创建的代理对象,Enhancer类似Proxy(代理类),由proxy.create()
创建代理对象。intercept()
与JDK动态代理的invoke()
类似。
本文中的例子是为了阐述JDK动态代理和Cglib动态代理的实现思路、方便大家理解而简单举例的,不一定有实用性。如果大家能理解代理的底层实现思路,那么,这对大家往后学习Spring事务管理、面向切面等知识和运用一定会有不小的帮助。
本文完结。