亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

spring aop底層原理及實現方法

發布時間:2021-04-26 14:56:29 來源:億速云 閱讀:129 作者:小新 欄目:開發技術

這篇文章主要介紹spring aop底層原理及實現方法,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

使用

要分析spring aop的底層原理,首先要會使用,先創建一個普通maven webapp項目,引入spring-context依賴,版本為5.1.1RELEASE

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.1.1.RELEASE</version>
    </dependency>

然后我使用aspectj作為aop的語法實現,和spring整合起來

<dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.4</version>
    </dependency>

接下來我全稱用注解的形式來模擬spring aop的使用,先創建一個配置類去掃描包,開啟aspectJ的自動代理支持

@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.ww")
public class Wconfig {

}

然后新建一個接口和接口的實現類

public interface Dao {
    void query();
}

@Component
public class IndexDao implements Dao{

    @Override
    public void query() {
        System.out.println("query......");
    }
}

創建切面

//代表是一個切面
@Aspect
@Component
public class WAspect {

    /**
     * execution表達式,可以百度寫法
     */
    @Pointcut("execution(* com.ww.dao.*.*(..))")
    public void point(){

    }

    /**
     * 在切點上進行前置通知
     */
    @Before("point()")
    public void beforeAd(){
        System.out.println("before-------------");
    }
}

創建測試方法

public class TestAspect {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext(Wconfig.class);
        Dao dao = configApplicationContext.getBean(Dao.class);
        dao.query();
    }
}

執行方法,可以看到在打印query...之前打印了before----------

spring aop底層原理及實現方法

這個時候我們很想知道為什么這句before會打印在query之前呢,稍微對spring aop有所了解的人應該知道,spring是通過動態代理和字節碼技術來實現aop操作的,也就是經常說的jdk動態代理和cglib動態代理兩種模式,那么,spring究竟是怎么創建的代理對象,又是什么時候產生的代理對象呢,下面我們來一起探究一下源碼,來揭開這個謎底

源碼分析

首先我們透過現象看本質,我先把斷點打在測試方法的最后一行,我們來看這個時候的dao對象

spring aop底層原理及實現方法

那么接下來我們就要去找到什么時候這個dao對象變成了動態代理對象的,既然在最后一行的時候對象已經變成了代理對象,那么我門自然就猜想是在上一句代碼的位置spring執行了創建代理對象的操作,我們把斷點移到上一行,debug進去

spring aop底層原理及實現方法

再往下走

spring aop底層原理及實現方法

這行代碼我看方法名覺得應該是有用的代碼,方法意思應該是spring處理好的bean,跟進去看看

@Nullable
	private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
        //這行代碼最有用,處理有beanName的bean,debug進入看一下
		NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
		if (namedBean != null) {
			return namedBean.getBeanInstance();
		}
		BeanFactory parent = getParentBeanFactory();
		if (parent instanceof DefaultListableBeanFactory) {
			return ((DefaultListableBeanFactory) parent).resolveBean(requiredType, args, nonUniqueAsNull);
		}
		else if (parent != null) {
			ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType);
			if (args != null) {
				return parentProvider.getObject(args);
			}
			else {
				return (nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable());
			}
		}
		return null;
	}
@SuppressWarnings("unchecked")
	@Nullable
	private <T> NamedBeanHolder<T> resolveNamedBean(
			ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {

		Assert.notNull(requiredType, "Required type must not be null");
		Class<?> clazz = requiredType.getRawClass();
		Assert.notNull(clazz, "Required type must have a raw Class");
        //候選name列表,直覺告訴我這行代碼比較重要
		String[] candidateNames = getBeanNamesForType(requiredType);

		if (candidateNames.length > 1) {
			List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
			for (String beanName : candidateNames) {
				if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
					autowireCandidates.add(beanName);
				}
			}
			if (!autowireCandidates.isEmpty()) {
				candidateNames = StringUtils.toStringArray(autowireCandidates);
			}
		}
        //因為我的代碼里只有一個bean,所以我覺得應該會執行這里的代碼
		if (candidateNames.length == 1) {
			String beanName = candidateNames[0];
			return new NamedBeanHolder<>(beanName, (T) getBean(beanName, clazz, args));
		}
		else if (candidateNames.length > 1) {
			Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length);
			for (String beanName : candidateNames) {
				if (containsSingleton(beanName) && args == null) {
					Object beanInstance = getBean(beanName);
					candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
				}
				else {
					candidates.put(beanName, getType(beanName));
				}
			}
			String candidateName = determinePrimaryCandidate(candidates, clazz);
			if (candidateName == null) {
				candidateName = determineHighestPriorityCandidate(candidates, clazz);
			}
			if (candidateName != null) {
				Object beanInstance = candidates.get(candidateName);
				if (beanInstance == null || beanInstance instanceof Class) {
					beanInstance = getBean(candidateName, clazz, args);
				}
				return new NamedBeanHolder<>(candidateName, (T) beanInstance);
			}
			if (!nonUniqueAsNull) {
				throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
			}
		}

		return null;
	}

執行完getBeanNamesForType(requiredType)后,我們看idea的變量顯示,果然有一個bean,name是IndexDao

spring aop底層原理及實現方法

那么接下來自然會進到length==1的那個代碼塊,這時候我再debug進入,這里還是一個getBean方法

spring aop底層原理及實現方法

spring aop底層原理及實現方法

在spring容器中還有一些沒有name的其他的bean需要被創建,所以這里我用上了條件斷點,當beanName等于indexDao的時候,才會進入斷點,但是當我F8跑完這行代碼的時候,出乎意料的事情發生了

spring aop底層原理及實現方法

驚不驚喜,意不意外,getSingleton這行代碼執行結束之后,代理對象就已經被創建了,所以需要debug進入這行代碼去看

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //spring所有的bean被放在ioc容器中的地方,就是這個singletonObjects,這是一個concorrentHashMap。
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

但是我在這里只看到了get方法,那么這些bean是什么時候放到singletonObjects里的呢,我來找找

protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.put(beanName, singletonObject);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.add(beanName);
		}
	}

在DefaultSingletonBeanRegistry注冊器中,我找到了singletonObjects.put方法,代表bean是這個時候被放到這個map里去的,接下來我在這行代碼上進行條件斷點,然后我們來看它的調用鏈,找出是什么時候執行的addSingleton方法,其實從這個時候我已經知道,斷點打在測試方法的倒數第二行是不對的,在getBean之前其實代理對象已經產生了

spring aop底層原理及實現方法

// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
                            //創建bean,核心代碼
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

在createBean方法上,我也加上條件斷點,然后debug進入

@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		if (logger.isTraceEnabled()) {
			logger.trace("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

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

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
            //核心代碼,創建bean實例,需要斷點進入
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

接下來我debug進入doCreateBean方法

debug跟進initializeBean方法,條件斷點在兩個初始化處理器上,我隱約覺得代理對象就是從這兩個方法中產生的,我們拭目以待

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}
        //包裝的bean
		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
            //執行前置初始化beanPostProcessor處理器
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
            //執行初始化后的beanPostProcessor處理器
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

執行完applyBeanPostProcessorsBeforeInitialization方法,這個時候我們看到warppedBean還是indexDao,并沒有產生代理對象

spring aop底層原理及實現方法

我猜想在下一個后置處理器中,代理對象將被創建,我debug進去

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

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
            //經過處理器處理后的bean,我先看看有多少個處理器
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

spring aop底層原理及實現方法

可以看到我的猜想被證明是正確的,運行完這個后置處理器,代理對象就被創建出來了。 到了這里我們知道了代理對象是從哪里來的了,但是還是沒搞清楚代理對象是怎么創建出來的,這時候我們就需要debug進入到這個處理器內部去瞧瞧了。

@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
            //獲取緩存key,不重要
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.contains(cacheKey)) {
                //重要方法,需要debug進去看
				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;
		}

		// Create proxy if we have advice.
        //看到上面這行注釋,可以確定代理類就是從這里產生的,下面這個方法得到的都是一些包括切點信息,通知類型等等的信息
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //顧名思義,創建代理,bebug進入看看
			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;
	}
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());
	}

    public Object getProxy(@Nullable ClassLoader classLoader) {
        //debug進去看看
		return createAopProxy().getProxy(classLoader);
	}
protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
        //同樣需要debug進入看看
		return getAopProxyFactory().createAopProxy(this);
	}

我們看到這里有一個if語句,當config中的isOptimize和isProxyTargetClass還有hasNoUserSuppliedProxyInterfaces三個判斷條件只要有一個滿足的話,spring就會選擇cglib的方式進行動態代理,而config中的兩個boolean變量的默認值都是false,而我們的被代理對象又是實現接口的,所以spring會選擇jdk動態代理的實現形式來完成動態代理,當然,我們也可以在這種情況下手動的配置config值來讓spring選擇cglib作為動態代理的實現方式,稍后我會演示

@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);
		}
	}

spring aop底層原理及實現方法

總結

我以spring aop實現的調用鏈圖來結束這次的總結

spring aop底層原理及實現方法

以上是“spring aop底層原理及實現方法”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

罗甸县| 姜堰市| 和静县| 金溪县| 昭觉县| 泸定县| 保康县| 清流县| 内乡县| 静乐县| 舟曲县| 南昌县| 屏东市| 鸡西市| 大埔县| 凤城市| 阳江市| 贵州省| 正蓝旗| 乐清市| 岳阳县| 郴州市| 黄平县| 麻江县| 聂拉木县| 佛坪县| 称多县| 松桃| 通江县| 碌曲县| 屯昌县| 元江| 环江| 蓬安县| 大冶市| 尚志市| 靖州| 通辽市| 洪雅县| 泗洪县| 绥阳县|