zoukankan      html  css  js  c++  java
  • 为什么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修饰注入。

  • 相关阅读:
    (HDOJ 2034)人见人爱AB
    (UVa 100) The 3n + 1 problem
    (HDOJ 2099)整除的尾数
    (UESTCOJ 1004)8球胜负(eight)
    asp.net中对数据库表插入null空值的问题
    利用模版生成html页
    如何取得IP/用户名等信息
    SQL SERVER的数据类型
    在IIS与.net框架中配置中把扩展名.aspx改成自定义的扩展名.mspx
    c#中什么情况下用(int)什么情况下用Convert.ToInt32?
  • 原文地址:https://www.cnblogs.com/root429/p/12799235.html
Copyright © 2011-2022 走看看