jdk和cglib动态代理及spring中的使用

本文主要讲解jdk与cglib的区别以及在spring中的实现原理,希望你阅读本文章后能对jdk和cglib有个清晰的认知。

JDK动态代理是面向接口,在创建代理实现类时比CGLib要快,创建代理速度快。

CGLib动态代理是通过字节码技术底层生成一个继承代理类的类来实现,然后重写代理类的方法(如果被代理类被final关键字所修饰,那么抱歉会失败,如果代理类中方法被final修饰,该方法无法代理成功),但是运行速度比JDK动态代理要快。

JDK代理

public interface UserService {
    void add();
}

实现类

public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("執行add");
    }
}

创建代理类,实现InvocationHandler接口

public class MyInvocationHandler implements InvocationHandler {
    private Object object;

    public MyInvocationHandler(Object object){
        this.object = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("方法執行前-----");
        Object result = method.invoke(object, args);
        System.out.println("方法執行后-----");
        return result;
    }
    public Object getProxy() {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),  object.getClass().getInterfaces(), this);
    }
}

测试类调用

public class ProxyTest {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(userService);
        UserService proxy = (UserService) myInvocationHandler.getProxy();
        proxy.add();
    }
}

执行结果

方法執行前-----
執行add
方法執行后-----

cglib动态代理

实例展示

实现MethodInterceptor接口

import org.springframework.cglib.proxy.MethodInterceptor;

public class MethodInterceptorImpl implements MethodInterceptor {

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("Before invoke");
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("After invoke");
        return result;
    }
}

类的调用

public class CglibDemp {

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(CglibDemp.class);
        enhancer.setCallback(new MethodInterceptorImpl());

        CglibDemp demp = (CglibDemp) enhancer.create();
        demp.test();

    }

    public void test(){
        System.out.println("CglibDeamo test()");
    }
}

返回结果

Before invoke
CglibDeamo test()
After invoke

 

spring中

spring源码实现

本方法在AopProxyFactory接口的实现类DefaultAopProxyFactory中,是spring获取aop代理选择jdk代理还是cglib动态代理的逻辑所在。

@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {		
        if (config.isOptimize() || config.isProxyTargetClass()||
               hasNoUserSuppliedProxyInterfaces(config)) {
			Class<?> targetClass = config.getTargetClass();
			if (targetClass == null) {
				throw new AopConfigException("TargetSource cannot determine target class: " +
						"Either an interface or a target is required for proxy creation.");
			}
               //代理类是否为接口,代理类是否为Proxy类派生出来的
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                        //jdk动态代理
				return new JdkDynamicAopProxy(config);
			}
                    //cglib动态代理
			return new ObjenesisCglibAopProxy(config);
		}
		else {
                     //jdk动态代理
			return new JdkDynamicAopProxy(config);
		}
	}

总结

  • spring中jdk代理的实现在JdkDynamicAopProxy类中,它也实现了InvocationHandler,所以可以看它的invoke的实现方法。
  • cglib代理,通过上面源码得知在ObjenesisCglibAopProxy类中实现,但是你进去会发现getProxy方法在它的父类CglibAopProxy中。如果你根据之前的示例留下的线索enhancer.setCallbacks方法一路追终下去会发现实现了MethodInterceptor接口的代理类都属于CglibAopProxy的内部类。

spring如何指定cglib动态代理?

代理类不是接口且不是Proxy类及其子类

在以上前提下有以下三种方式:

  1.  proxy-target-class 属性设为true。
  2. 目标类没有实现接口。
  3. 使用激进的优化策略。

参考:《spring源码深度解析》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值