專注於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修飾注入。