自我分析-Spring AOP

Spring AOP直白的來說就是使用了JDK的動態代理和CGLIB對Bean的代理,從而實現方法增強的效果。

注意:

1.分析框架代碼時,要常使用類繼承、調用關係等快捷鍵,可以更高效的學習,快捷鍵可以設置成你習慣的按鍵;

2.本文重在怎麼自我分析框架代碼,所以對其中解析需自己實際跟蹤代碼實踐方可;

3.spring源代碼版本 spring-framework-3.2.1.RELEASE。


預覽

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory,自動裝箱BeanFactory。

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator,代理對象創建類。

org.springframework.aop.framework.JdkDynamicAopProxy,JDK動態代理類。

org.springframework.aop.framework.CglibAopProxy,CGLIB動態代理類。



入口-createBean

前面我們分析Spring IOC時,瞭解了IOC的資源定位、加載、註冊等步驟,但是對於AOP的實現還未分析。

還記得createBean嘛,這裏就是實際創建Bean的入口,在getBean中調用了。


org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

public <T> T createBean(Class<T> beanClass) throws BeansException {
		// Use prototype bean definition, to avoid registering bean as dependent bean.
		RootBeanDefinition bd = new RootBeanDefinition(beanClass);
		bd.setScope(SCOPE_PROTOTYPE);
		bd.allowCaching = false;
		return (T) createBean(beanClass.getName(), bd, null);
	}
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
			throws BeanCreationException {

		if (logger.isDebugEnabled()) {
			logger.debug("Creating instance of bean '" + beanName + "'");
		}
		// Make sure bean class is actually resolved at this point.
		resolveBeanClass(mbd, beanName);

		// Prepare method overrides.
		try {
			mbd.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// 產生 AOP 代理對象的入口
			Object bean = resolveBeforeInstantiation(beanName, mbd);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		Object beanInstance = doCreateBean(beanName, mbd, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}


對象實例化前處理

在對象實例化前做相應的邏輯處理,即是否需創建代理對象

protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName)
			throws BeansException {

		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				// 在對象實例化前的處理操作
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

在實例化前會判斷是否存在AOP的代理,而此方法的實現在org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator。

<strong>	</strong>public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (beanName == null || !this.targetSourcedBeans.containsKey(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		if (beanName != null) {
			TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
			if (targetSource != null) {
				this.targetSourcedBeans.put(beanName, Boolean.TRUE);
				// 獲取通知點即需增強效果的接口,如想了解可查看其子類AbstractAdvisorAutoProxyCreator
				Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
				// 根據類名、需增強接口等信息創建代理對象
				Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
				this.proxyTypes.put(cacheKey, proxy.getClass());
				return proxy;
			}
		}

		return null;
	}


生產代理對象的準備工作

接下來將看到一系列的準備工作:代理工廠、目標對象的接口、目標對象的通知者等。

<span style="white-space:pre">	</span>protected Object createProxy(
			Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

		ProxyFactory proxyFactory = new ProxyFactory();
		// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
		proxyFactory.copyFrom(this);

		if (!shouldProxyTargetClass(beanClass, beanName)) {
			// 獲取所有目標對象的接口
			Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
			for (Class<?> targetInterface : targetInterfaces) {
				proxyFactory.addInterface(targetInterface);
			}
		}

		// 通過通知點即類名創建通知者(切入點及增強效果的集合)
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		for (Advisor advisor : advisors) {
			proxyFactory.addAdvisor(advisor);
		}

		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		// 通過工廠和proxyClassLoader來獲取代理對象
		return proxyFactory.getProxy(this.proxyClassLoader);
	}


創建JDK動態代理 OR CGLIB

<span style="white-space:pre">	</span>public Object getProxy(ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader); //使用
	}

此處的createAopProxy(),是使用org.springframework.aop.framework.DefaultAopProxyFactory中的createAopProxy來

創建JdkDynamicAopProxy還是CglibProxyFactory。

其中JDK的動態代理只能對接口型的目標對象進行代理,而CGLIB沒有此限制,代碼中我們可以明確的看到。

<span style="white-space:pre">	</span>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()) { // 目標對象若是接口,即生產JDK的動態代理
				return new JdkDynamicAopProxy(config);
			}
			return CglibProxyFactory.createCglibProxy(config); // 非接口型目標對象,即使用CGLIB來實現代理。
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}


接下來就是的getProxy生產代理對象就要看JdkDynamicAopProxy和CglibProxyFactory兩個類了,若對兩者的動態代理不熟悉,先實現瞭解下,

再接着分析。

JDK動態代理:http://blog.csdn.net/xiaohai0504/article/details/6884925

CGLIB動態代理:http://blog.csdn.net/xiaohai0504/article/details/6832990




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章