- 1.动态代理
- 2.jdk动态代理
- 3.CGLIB动态代理
- 4.动态代理的作用
- 5.jdk动态代理实现步骤
动态代理是指,程序在整个运行过程中根本就不存在目标类的代理类,目标对象的代理对象只是由代理生成工具(不是真实定义的类)在程序运行时由JVM根据反射等机制动态生成的。代理对象与目标对象的代理关系在程序运行时才成立。
2.jdk动态代理 动态代理的实现方式常用的有两种:使用JDK的proxy,与通过CGLIB生成代理。
jdk的动态要求目标对象必须实现接口,这是java设计上的要求。
从jdk1.3以来,jdk语言通过java.lang.reflect包提供了三个类支持代理模式Proxy,Method和InovcationHandler。
CGLib (Code Generation Library) 是一个开源项目。是一个强大的,高性能,高质量的Code生成库,它可以在运行期扩展java类与实现java接口。它广泛的被许多AOP的框架使用,例如Spring AOP。
使用JDK的proxy实现代理,要求目标类与代理类实现相同的接口。若目标类不存在接口,则无法使用该方法实现。但对于无接口的类,要为其创建动态代理,就要使用CGLIB来实现。
CGLIB代理的生成原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象。所以,使用CGLIB生成动态代理,要求目标类必须能够被继承,即不能是final的类。
CGLIB经常被应用在框架中,例如spring,hibernate等。cglib的代理效果高于jdk。项目中直接使用动态代理的地方不多。一般都使用框架提供的功能。
总结:第三方的工具库,创建代理对象,原理是继承。通过继承目标类,创建子类。子类就是代理对象。要求目标类不能是final的,方法也不能是final的。
4.动态代理的作用- 1)在目标类源代码不改变的情况下,增加功能。
- 2)减少代码的重复
- 3)专注业务逻辑代码
- 4)解耦合,让你的业务功能和日志,事务非业务功能分离。
动态代理:可以在程序的执行过程中,创建代理对象。
通过代理对象执行方法,给目标类的方法增加额外的功能(功能增强)
- 1.创建目标类,SomeServiceImpl目标类,给它的doSome,doOther增加 输出时间,事务。
package com.putao.service;
public interface SomeService {
void doSome();
void doOther();
}
package com.putao.service.impl;
import com.putao.service.SomeService;
import com.putao.util.ServiceTools;
import java.util.Date;
//service类的代码不修改,也能增加 输出时间,事务。
public class SomeServiceImpl implements SomeService {
@Override
public void doSome() {
System.out.println("执行业务方法doSome");
int res = 10 + 20;
//更新购买商品的库存,生成订单,结算整个购买商品的总价
}
@Override
public void doOther() {
System.out.println("执行业务方法doOther");
}
}
- 2.创建InvocationHandler接口的实现类,在这个类中实现给目标方法增加功能。
ServiceTools工具类
package com.putao.util;
import java.util.Date;
public class ServiceTools {
public static void doLog(){
System.out.println("非业务方法,方法的执行时间:"+new Date());
}
public static void doTrans(){
//方法的最后,提交事务
System.out.println("非业务方法,方法执行完毕后,提交事务");
}
}
实现类
package com.putao.handler;
import com.putao.util.ServiceTools;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private Object target; //SomeServiceImpl
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//通过代理对象执行方法时,会调用执行这个invoke()
System.out.println("执行MyInvocationHandler中的invoke");
System.out.println("method名称:"+method.getName());
String methodName = method.getName();
Object res = null;
if ("doSome".equals(methodName)){//JoinPoint PointCut
ServiceTools.doLog();//在目标方法之前,输出时间
//执行目标类的方法,通过Method类实现
res = method.invoke(target,args); //SomeServiceImpl.doSome()
ServiceTools.doTrans();//在目标方法执行之后,提交事物
}else {
res = method.invoke(target,args); //SomeServiceImpl.doOther()
}
//目标方法执行结果
return res;
}
}
- 3.使用jdk中的类Proxy,创建代理对象。实现创建对象的能力。
package com.putao;
import com.putao.handler.MyInvocationHandler;
import com.putao.service.SomeService;
import com.putao.service.impl.SomeServiceImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class MyApp {
public static void main(String[] args) {
//调用doSome,doOther
// SomeService service = new SomeServiceImpl();
// service.doSome();
// System.out.println("================");
// service.doOther();
//使用jdk的Proxy创建代理对象
//创建目标对象
SomeService target = new SomeServiceImpl();
//创建InvocationHandler对象
InvocationHandler handler = new MyInvocationHandler(target);
//创建代理
SomeService proxy = (SomeService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),handler);
//com.sun.proxy.$Proxy0
System.out.println("proxy===="+proxy.getClass().getName());
//通过代理执行方法,会调用handler中的invoke()
proxy.doSome();
System.out.println("==================");
proxy.doOther();
}
}



