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

背景

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

class com.workit.demo.service.ServiceA$$EnhancerBySpringCGLIB$$4ee00fa9

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

class com.workit.demo.service.ServiceA

下面我們就帶着這個疑問爲什麼會出現這樣的情況吧。我們可以根據spring ioc創建bean的源碼調試最終確認是在哪裏爲其生成代理類的
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization這個方法如果看過spring 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;
	}
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} 

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

  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());

至於爲什麼如果有@Repository這個方法isEligible就會返回true的話,是因爲isEligible方法裏面會去判斷當前類上面是否有註解Repository,如果有,spring則爲其創建一個代理類。
總結
spring項目中如果引用了spring-tx的依賴,並且類上面被打上@Repository註解的類,spring都會被爲其生存一個代理類。爲何會生成一個代理類,主要的原因在PersistenceExceptionTranslationPostProcessor這個類,這個類是位於spring-tx下面的。如果我們希望得到一個原生類的話要麼不引入spring-tx模塊,或者不在類上面用Repository修飾注入。

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