1.适用场景(基于cglib实现的动态代理):
当我们需要给没有实现接口的目标类生成代理对象时,jdk的动态代理就完成不了这样的事情了,这时我们就可以继承目标类,以目标类的子类方式实现,这样的方法叫做cglib的动态代理,也可以叫做子类代理,它是在内存中构建一个子类对象从而对目标对象进行功能的增强。
2.上代码:
/**
* cglib动态代理原方法
* @author xpzhang
*
*/
public class Refund {
public void refund() {
System.out.println("我是退款原逻辑");
}
}
/**
* 基于cglib实现的动态代理
* @author xpzhang
*
*/
public class CglibProxyFactory implements MethodInterceptor{
//维护目标对象
private Object target;
public CglibProxyFactory(Object target) {
this.target = target;
}
/**
* 获得目标类的代理对象
* @return
*/
public Object getObject() {
//工具类
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(target.getClass());
//设置回调
enhancer.setCallback(this);
//创建代理类
Object object = enhancer.create();
return object;
}
@Override
public Object intercept(Object arg0, Method method, Object[] objects, MethodProxy arg3) throws Throwable {
System.out.println("cglib代理前退款的逻辑");
//执行目标对象的目标方法
method.invoke(target,objects);
System.out.println("cglib代理后退款新增逻辑");
return null;
}
}
/**
* cglib测试类
* @author xpzhang
*
*/
public class MainTest {
public static void main(String[] args) {
Refund refund = new Refund();
Refund proxyObject = (Refund) new CglibProxyFactory(refund).getObject();
proxyObject.refund();
}
}
3.基于JDK实现的动态代理,上代码:
/**
* 交易接口
* @author PengMvc
*
*/
public interface Itransfer {
// 退款
public void refund();
}
/*
* 对退款接口进行功能增强,譬如新增核对交易信息
*/
public class RefundImpl implements Itransfer{
@Override
public void refund() {
System.out.println("调用退款接口进行退款了!");
}
}
/**
* 基于jdk的动态代理
* @author PengMvc
*
*/
public class RefundProxy implements InvocationHandler{
// 目标对象
private Object target;
public void setTarget(Object target) {
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(target, args);
// 这里添加增强的功能
System.out.println("<基于JDK进行功能增强>:退完款了,准备调用交易明细接口进行核对了!");
return result;
}
// 获取代理对象
public Object getProxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}
/**
* 测试类
* @author PengMvc
*
*/
public class TestDynamicProxy {
public static void main(String[] args) {
RefundProxy refundProxy = new RefundProxy();
refundProxy.setTarget(new RefundImpl());
Object proxyInstance = refundProxy.getProxyInstance();
((Itransfer) proxyInstance).refund();;
}
}
4.基于jdk的动态代理实现:
/**
* 退款的表现层入口
* @author PengMvc
*
*/
public class RefundController {
private Irefund refund = (Irefund) RefundProxy.getProxyInstance(new RefundImpl());
public Boolean refund() {
return refund.refund();
}
public static void main(String[] args) {
RefundController refundController = new RefundController();
Boolean flag = refundController.refund();
String resultMsg = flag ? "退款和清分成功":"退款和清分失败";
System.out.println(resultMsg);
}
}
/**
* 退款接口
* @author PengMvc
*
*/
public interface Irefund {
public Boolean refund();
}
/**
* 退款接口的具体实现类
* @author PengMvc
*
*/
public class RefundImpl implements Irefund{
@Override
public Boolean refund() {
System.out.println("这里是具体的退款业务逻辑");
return true;
}
}
/**
* 这是一个通用的接口
* 通过动态代理对现有功能进行增强
* @author PengMvc
*
*/
public class RefundProxy implements InvocationHandler {
private static final RefundProxy commonProxy = new RefundProxy();
private Iclearing clear = new ClearingImpl();
private Object target;
// 需要增强的类(被代理对象)
private static void setTarget(Object target) {
commonProxy.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Boolean ifRefund = (Boolean) method.invoke(target,args);
System.out.println("<退款结束通过动态代理对现有功能进行增强>"+ifRefund);
Boolean ifClearing = clear.clearing();
Boolean ifSuccessFlag = (ifClearing && ifRefund) ? true : false;
return ifSuccessFlag;
}
public static Object getProxyInstance(Object target) {
if(target == null) {
throw new InaccessibleObjectException("设置被代理对象出错!");
}
setTarget(target);
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), commonProxy);
}
}
/**
* 清分接口
* @author PengMvc
*
*/
public interface Iclearing {
public Boolean clearing();
}
/**
* 清分接口实现类
* @author PengMvc
*
*/
public class ClearingImpl implements Iclearing{
@Override
public Boolean clearing() {
System.out.println("这里是清分的具体逻辑");
return false;
}
}
5.总结:利用动态代理,可以在不改变业务类逻辑的前提下,对业务类进行功能的增强,在开发中如果有接口的我们可以用jdk的动态代理,若没有接口,我们可以用基于cglib的动态代理、一般情况下,我们很少使用静态代理,因为静态代理对子类的维护成本太高了。