為什麼spring 被@Repository註解標識注入後是代理類

專注於Java領域優質技術,歡迎關注

背景

今天發現一個奇怪的問題,有一個類是用的@Repository註解標識注入的,並且這個類並沒有配置任何帶代理和aop配置。但是得到的這個類不是一個原生類,而是一個代理類,如果換成了Component註解這時候得到的類就是原生類 。下面分別演示下這兩種情況。先用@Repository注入得到的class是下面的:

<code>class com.workit.demo.service.ServiceA$EnhancerBySpringCGLIB$4ee00fa9
/<code>

然後@Component注入得到的class是下面的:

<code>class com.workit.demo.service.ServiceA
/<code>

下面我們就帶著這個疑問為什麼會出現這樣的情況吧。我們可以根據spring ioc創建bean的源碼調試最終確認是在哪裡為其生成代理類的AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization這個方法如果看過spring ioc源碼的人應該都比較熟悉。

<code>	@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;
	}
/<code>
<code>getBeanPostProcessors() 總共有12個beanProcessors
result = {CopyOnWriteArrayList@4450}  size = 12
 0 = {ApplicationContextAwareProcessor@4480} 
 1 = {WebApplicationContextServletContextAwareProcessor@4481} 
 2 = {ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor@4482} 
 3 = {PostProcessorRegistrationDelegate$BeanPostProcessorChecker@4483} 
 4 = {ConfigurationPropertiesBindingPostProcessor@4484} 
 5 = {MethodValidationPostProcessor@4391} "proxyTargetClass=true; optimize=false; opaque=false; exposeProxy=false; frozen=false"
 6 = {PersistenceExceptionTranslationPostProcessor@4485} "proxyTargetClass=true; optimize=false; opaque=false; exposeProxy=false; frozen=false"
 7 = {WebServerFactoryCustomizerBeanPostProcessor@4486} 
 8 = {ErrorPageRegistrarBeanPostProcessor@4487} 
 9 = {CommonAnnotationBeanPostProcessor@4488} 
 10 = {AutowiredAnnotationBeanPostProcessor@4489} 
 11 = {ApplicationListenerDetector@4490} 
/<code>

經過斷點調試我們最終發現為其生成代理類的是這個PersistenceExceptionTranslationPostProcessor。進入這個類的postProcessAfterInitialization方法,由於PersistenceExceptionTranslationPostProcessor繼承了AbstractAdvisingBeanPostProcessor所以調用的是AbstractAdvisingBeanPostProcessor的postProcessAfterInitialization方法創建代理類的方法就是

<code>  if (this.isEligible(bean, beanName)) {
                ProxyFactory proxyFactory = this.prepareProxyFactory(bean, beanName);
                if (!proxyFactory.isProxyTargetClass()) {
                    this.evaluateProxyInterfaces(bean.getClass(), proxyFactory);
                }

                proxyFactory.addAdvisor(this.advisor);
                this.customizeProxyFactory(proxyFactory);
                return proxyFactory.getProxy(this.getProxyClassLoader());
/<code>

至於為什麼如果有@Repository這個方法isEligible就會返回true的話,是因為isEligible方法裡面會去判斷當前類上面是否有註解Repository,如果有,spring則為其創建一個代理類。

總結

spring項目中如果引用了spring-tx的依賴,並且類上面被打上@Repository註解的類,spring都會被為其生存一個代理類。為何會生成一個代理類,主要的原因PersistenceExceptionTranslationPostProcessor這個類,這個類是位於spring-tx下面的。如果我們希望得到一個原生類的話要麼不引入spring-tx模塊,或者不在類上面用Repository修飾注入。


分享到:


相關文章: