一、jdk实现原理
1、接口
package top.einino.service;
public interface BankService {
void getMoney( Double money);
}
2、接口实现类
package top.einino.service.impl;
import top.einino.service.BankService;
public class BankServiceImpl implements BankService {
public void getMoney(Double money) {
System.out.println(“取出:”+money+”元”);
}
}
3、代理机制
package top.einino.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKProxy implements InvocationHandler {
private Object target;//要代理的目标对象
public JDKProxy(Object target){
this.target = target;
}
public Object createProxy(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),//类加载
target.getClass().getInterfaces(),//类接口
this);//实现invocationHandler接口
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println(“写入日记”);
Object result = method.invoke(target, args);
return result;
}
}
4、测试
package top.einino.junit;
import top.einino.proxy.JDKProxy;
import top.einino.service.BankService;
import top.einino.service.impl.BankServiceImpl;
public class TestJdkProxy {
public static void main(String[] args) {
//代理的目标对象
BankServiceImpl bankServiceImpl = new BankServiceImpl();
//实现代理的类
JDKProxy jdkProxy = new JDKProxy(bankServiceImpl);
//创建代理对象
BankService bankServiceProxy = (BankService) jdkProxy.createProxy();
//执行操作
bankServiceProxy.getMoney(2000.0d);
}
}
缺点: 使用Jdk动态代理,必须要求target目标对象,实现接口 ,如果没有接口,不能使用Jdk动态代理
二、Cglib动态代理实现原理
1、无接口的类
package top.einino.service.impl;
public class BankServiceWithCglib {
public void getMoney(Double money) {
System.out.println(“取出:”+money+”元”);
}
}
2、创建代理类
package top.einino.proxy;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor{
private Object target;//要代理的目标对象
public CglibProxy(Object target){
this.target = target;
}
public Object createProxy(){
//创建enhancer对象
Enhancer enhancer = new Enhancer();
//创建代理,对目标对象,创建子类对象
enhancer.setSuperclass(target.getClass());
//传入callback对象,对目标增强
enhancer.setCallback(this);
return enhancer.create();
}
//第一个参数代理对象,第二个参数代理方法,第三个参数代理方法参数列表,第四个参数代理对象的代理方法
@Override
public Object intercept(Object proxy, Method method, Object[] arg2,
MethodProxy methodProxy) throws Throwable {
System.out.println(“写入日记”);
return methodProxy.invokeSuper(proxy, arg2);
}
}
3、测试
package top.einino.junit;
import top.einino.proxy.CglibProxy;
import top.einino.service.BankService;
import top.einino.service.impl.BankServiceWithCglib;
public class TestCglibProxy {
public static void main(String[] args) {
//代理的目标对象
BankServiceWithCglib bankServiceWithCglib = new BankServiceWithCglib();
//执行代理的代理类
CglibProxy cglibProxy = new CglibProxy(bankServiceWithCglib);
//创建代理对象
BankServiceWithCglib BankServiceWithCglibProxy = (BankServiceWithCglib) cglibProxy.createProxy();
//执行操作
BankServiceWithCglibProxy.getMoney(2000.0d);
}
}
三、两者对比
Cglib 创建代理思想: 对目标类创建子类对象
设置 superClass 对哪个类创建子类 (类似 JDK代理 接口)
设置 callback 实现增强代码 (类似 JDK代理 InvocationHandler )
在cglib的callback函数中,要执行被代理对象的方法
method.invoke(target, args); 等价于 methodProxy.invokeSuper(proxy, args);
优先对接口代理 (使用JDK代理),如果目标没有接口,才会使用cglib代理 !
四、小结
该博文主要介绍了spring的aop实现原理,以及这两个原理的对比和实际运用时是如何调用。
如果有疑问或者对该博文有何看法或建议或有问题的,欢迎评论,恳请指正!