zoukankan      html  css  js  c++  java
  • Spring AOP分析(3) -- CglibAopProxy实现AOP

    上文探讨了应用JDK动态代理实现Spring AOP功能的方式,下面将继续探讨Spring AOP功能的另外一种实现方式 -- CGLIB。

    首先,来看看类名CglibAopProxy,该类实现了两个接口:一个是AopProxy接口,一个是Serializable接口。直接忽略Serializable接口,AopProxy接口中只定义了两个同名方法getProxy。如下所示:

    class CglibAopProxy implements AopProxy, Serializable
    

    类中有一个非常重要的属性advised,该属性在JdkDynamicAopProxy中也存在,主要用于配置代理信息,是一个非常重要的属性,如下

    protected final AdvisedSupport advised;
    

    属性为final类型,可以被子类继承,一旦赋值后便不能改变。在CglibAopProxy中,advised在构造器中被赋值,后续不可更改:

    	public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
    		Assert.notNull(config, "AdvisedSupport must not be null");
    		if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
    			throw new AopConfigException("No advisors and no TargetSource specified");
    		}
    		this.advised = config;
    		this.advisedDispatcher = new AdvisedDispatcher(this.advised);
    	}
    

    跟JdkDynamicAopProxy一样,实现了AopProxy接口,实现了getProxy()方法,如下:

    	@Override
    	public Object getProxy(ClassLoader classLoader) {
    		if (logger.isDebugEnabled()) {
    			logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
    		}
    
    		try {
    			Class<?> rootClass = this.advised.getTargetClass();
    			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
    
    			Class<?> proxySuperClass = rootClass;
    			if (ClassUtils.isCglibProxyClass(rootClass)) {
    				proxySuperClass = rootClass.getSuperclass();
    				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
    				for (Class<?> additionalInterface : additionalInterfaces) {
    					this.advised.addInterface(additionalInterface);
    				}
    			}
    
    			// Validate the class, writing log messages as necessary.
    			validateClassIfNecessary(proxySuperClass, classLoader);
    
    			// Configure CGLIB Enhancer...
    			Enhancer enhancer = createEnhancer();
    			if (classLoader != null) {
    				enhancer.setClassLoader(classLoader);
    				if (classLoader instanceof SmartClassLoader &&
    						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
    					enhancer.setUseCache(false);
    				}
    			}
    			enhancer.setSuperclass(proxySuperClass);
    			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    			enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
    
    			Callback[] callbacks = getCallbacks(rootClass);
    			Class<?>[] types = new Class<?>[callbacks.length];
    			for (int x = 0; x < types.length; x++) {
    				types[x] = callbacks[x].getClass();
    			}
    			// fixedInterceptorMap only populated at this point, after getCallbacks call above
    			enhancer.setCallbackFilter(new ProxyCallbackFilter(
    					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
    			enhancer.setCallbackTypes(types);
    
    			// Generate the proxy class and create a proxy instance.
    			return createProxyClassAndInstance(enhancer, callbacks);
    		}
    		catch (CodeGenerationException ex) {
    			throw new AopConfigException("Could not generate CGLIB subclass of class [" +
    					this.advised.getTargetClass() + "]: " +
    					"Common causes of this problem include using a final class or a non-visible class",
    					ex);
    		}
    		catch (IllegalArgumentException ex) {
    			throw new AopConfigException("Could not generate CGLIB subclass of class [" +
    					this.advised.getTargetClass() + "]: " +
    					"Common causes of this problem include using a final class or a non-visible class",
    					ex);
    		}
    		catch (Throwable ex) {
    			// TargetSource.getTarget() failed
    			throw new AopConfigException("Unexpected AOP exception", ex);
    		}
    	}
    

    在创建代理过程中需要判断被代理类是否已经进行过验证,若没有验证过则执行验证。验证方法如下:

    	private void doValidateClass(Class<?> proxySuperClass, ClassLoader proxyClassLoader, Set<Class<?>> ifcs) {
    		if (proxySuperClass != Object.class) {
    			Method[] methods = proxySuperClass.getDeclaredMethods();
    			for (Method method : methods) {
    				int mod = method.getModifiers();
    				if (!Modifier.isStatic(mod)) {
    					if (Modifier.isFinal(mod)) {
    						if (implementsInterface(method, ifcs)) {
    							logger.warn("Unable to proxy interface-implementing method [" + method + "] because " +
    									"it is marked as final: Consider using interface-based JDK proxies instead!");
    						}
    						logger.info("Final method [" + method + "] cannot get proxied via CGLIB: " +
    								"Calls to this method will NOT be routed to the target instance and " +
    								"might lead to NPEs against uninitialized fields in the proxy instance.");
    					}
    					else if (!Modifier.isPublic(mod) && !Modifier.isProtected(mod) && !Modifier.isPrivate(mod) &&
    							proxyClassLoader != null && proxySuperClass.getClassLoader() != proxyClassLoader) {
    						logger.info("Method [" + method + "] is package-visible across different ClassLoaders " +
    								"and cannot get proxied via CGLIB: Declare this method as public or protected " +
    								"if you need to support invocations through the proxy.");
    					}
    				}
    			}
    			doValidateClass(proxySuperClass.getSuperclass(), proxyClassLoader, ifcs);
    		}
    	}
    

    接着配置CGLIB加强createEnhancer(),最后创建代理类生成代理实例createProxyClassAndInstance(enhancer, callbacks)

  • 相关阅读:
    mysql查看锁表情况
    利用xtrabackup备份mysql数据库
    /proc/sys/vm/参数
    linux的sysctl基本配置
    python计算apache总内存
    ip_conntrack table full dropping packet错误的解决方法
    apachetop 实时监控apache指定日志
    mysql大表myisam的导入
    编译安装php5.5和php-fpm
    tshark 抓包分析
  • 原文地址:https://www.cnblogs.com/hthuang/p/7797595.html
Copyright © 2011-2022 走看看