背景
今天發現一個奇怪的問題,有一個類是用的@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修飾注入。