• 为什么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修饰注入。

  • 相关阅读:
    Linux 下的类似Windows下Everything的搜索工具
    windows和linux环境下制作U盘启动盘
    程序调试手段之gdb, vxworks shell
    LeetCode 1021. Remove Outermost Parentheses (删除最外层的括号)
    LeetCode 1047. Remove All Adjacent Duplicates In String (删除字符串中的所有相邻重复项)
    LeetCode 844. Backspace String Compare (比较含退格的字符串)
    LeetCode 860. Lemonade Change (柠檬水找零)
    LeetCode 1221. Split a String in Balanced Strings (分割平衡字符串)
    LeetCode 1046. Last Stone Weight (最后一块石头的重量 )
    LeetCode 746. Min Cost Climbing Stairs (使用最小花费爬楼梯)
  • 原文地址:https://www.cnblogs.com/root429/p/12799235.html
Copyright © 2020-2023  润新知