cglib动态代理实现,和JDK动态代比较

首先我们看一下cglib是怎么实现动态代理的:

上代码:

/**
 * 被代理的某一个类,注意,没有实现任何的一个接口
 */
public class SubjectService {

    public String doSomethings(String needTool){
        System.out.println("用" + needTool + "做一些事情");
        return "调用成功";
    }
}

特别注意,cglib实现动态代理,被代理的类是可以不用实现任何接口的,就像上面一个普通类,

但是要注意的是,这个普通的类不能用final修饰,因为cglib技术是动态生成字节码技术,这个动态代理会生成一个继承被代理类的类的字节码。(很拗口)

接下来就是要写一个方法增强类了

public class SubjectMethodInterceptor implements MethodInterceptor {

    /**
     * obj:cglib生成的代理对象 "this", the enhanced object(增强的对象)
     * method:被代理对象方法 intercepted Method 拦截(代理)的方法
     * args:方法入参 argument array; primitive types are wrapped (参数数组,原始类型被包装)
     * proxy: 代理方法 用户调用super的非拦截(没有代理)的方法,但是是可能被调用
     */
    public Object intercept(Object obj, java.lang.reflect.Method method, 
                                Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("======做某事之前准备======");
        Object object = proxy.invokeSuper(obj, args);
        System.out.println("======做某事之后收尾======");
        return object;
    }
}

注意上面参数的注释

接下来就是要测试了

public class CglibTest {

    public static void main(String[] args) {
        // 通过CGLIB动态代理获取代理对象的过程
        Enhancer enhancer = new Enhancer();
        // 设置enhancer对象的父类
        enhancer.setSuperclass(SubjectService.class);
        // 设置enhancer的回调对象
        enhancer.setCallback(new SubjectMethodInterceptor());
        // 创建代理对象(增强对象)
        SubjectService proxy= (SubjectService)enhancer.create();
        // 通过代理对象调用目标方法
        proxy.doSomethings("锤子");

    }

}

运行结果:

======做某事之前准备======
用锤子做一些事情
======做某事之后收尾======

上面就是cglib实现动态代理的简单实现

虽然有点废话,但是还是像介绍一下cglib

CGLIB(Code Generation Library)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java

类与实现Java接口。Hibernate用它来实现PO(Persistent Object 持久化对象)字节码的动态生成。CGLIB是一个强大的高性能的

代码生成包。它广泛的被许多AOP的框架使用,例如Spring AOP为他们提供方法的interception(拦截)。CGLIB包的底层是通

过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。除了CGLIB包,脚本语言例如Groovy和BeanShell,也

是使用ASM来生成java的字节码。

值得注意的是:

当然不推荐直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。(笔者也不敢用)

经过上面的介绍,我们肯定知道了它和JDK动态代理的区别

1. cglib是基于动态生成字节码,JDK基于Java反射机制

2. cglib被代理的类可以不实现任何的接口,JDK需要实现接口

3. 效率上,Java8之后jdk的运行效率,还是生成代理的效率都比cglib高。

但是cglib虽然效率上已经落后,但还是有应用的,springAOP中,要实现接口的,用的是JDK代理,没有实现人任何接口的还是会使用cglib技术。

就像下面的安利一样:

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

	@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.");
			}
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

	/**
	 * Determine whether the supplied {@link AdvisedSupport} has only the
	 * {@link org.springframework.aop.SpringProxy} interface specified
	 * (or no proxy interfaces specified at all).
	 */
	private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
		Class[] ifcs = config.getProxiedInterfaces();
		return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
	}

}

 

你可能感兴趣的:(设计模式)