cglib动态代理


首先我们看一下如何实现cglib的动态代理


cglib通过实现MethodInterceptor接口来实现动态代理

public class DemoMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before in cglib");
        Object result = null;
        try{
            result = methodProxy.invokeSuper(o, objects);
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }finally {
            System.out.println("after in cglib");
        }
        return result;
    }
}

下面代码是告诉我们如何实现cglib的调用

public class MethodInterceptorClient {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(RealSubject.class);
        enhancer.setCallback(new DemoMethodInterceptor());
        Subject subject = (Subject) enhancer.create();
        subject.hello();
    }
}


JDK与Cglib代理对比

JDK只能针对有接口的类的接口方法进行动态代理
Cglib基 于继承来实现代理,无法对static、final类进行代理,
Cglib基于继承来实现代理,无法对private、static方法进行代理

最后我们看看Spring还如何创建动态代理类的

cglib动态代理_第1张图片

下面我们看一下DefalutAopProxyFactory

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    public DefaultAopProxyFactory() {
    }

    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            return new JdkDynamicAopProxy(config);
        } else {
            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.");
            } else {
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }

    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
        Class<?>[] ifcs = config.getProxiedInterfaces();
        return ifcs.length == 0 || ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0]);
    }
}

在代码中我们可以看到有!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)这三个选项,如果这三个都不满足就会走JDK的实现。或者本身是JDK代理的话也会走JDK代理,其他都是走cglib代理


那我们如何强制使用cglib呢

@SpringBootApplication
// 强制使用cglib
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AopDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(AopDemoApplication.class, args);
    }
}

总结:
如果目标对象实现了接口,则默认采用JDK动态代理
如果目标对象没有实现接口,则采用Cglib进行动态代理
如果目标对象实现了接口,且强制cglib代理,则使用cglib代理

你可能感兴趣的:(Java)