1. 程式人生 > 其它 >Nowcoder 智乃醬的子集與超集 (高維字首和)

Nowcoder 智乃醬的子集與超集 (高維字首和)

AOP原始碼分析

gradle引入aop的依賴:

group 'org.springframework'
version '5.1.21.BUILD-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile(project(":spring-context"))
    compile group:'org.aspectj',name:'aspectjweaver',version: '1.8.6'
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

我們知道AOP的實現是使用的動態代理的方式,那必然是在建立物件的時候建立了一個代理物件。

那麼代理類是什麼時候建立的呢?實際上代理類的建立是通過BeanPostProcessor的後置處理來做的。

經過之前IOC原始碼的學習,我們可以知道,後置處理器的程式碼的位置。

@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

它會遍歷所有實現了BeanPostProcessor的Bean,其中有一個AspectJAwareAdvisorAutoProxyCreator,看名字就知道跟AOP是相關的。既然它實現了BeanPostProcessor介面,我們就要去找它的postProcessAfterInitialization
方法。

當前類沒有,就往父類裡面找,在AbstractAutoProxyCreator裡面找到

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

跟蹤wrapIfNecessary方法進入

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// 如果有設定增強的話,就建立代理物件
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

可以看出如果有設定aop相關增強的話,就會去呼叫createProxy方法,建立並返回代理物件。

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

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

		return proxyFactory.getProxy(getProxyClassLoader());
	}

我們點proxyFactory.getProxy這個方法,發現他有兩個實現。

接下來就會根據這兩個不同的實現創建出代理物件,對原方法進行增強。

書山有路勤為徑,學海無涯苦作舟