背景

今天发现一个奇怪的问题,有一个类是用的@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修饰注入。

为什么spring 被@Repository注解标识注入后是代理类的更多相关文章

  1. Spring之基于注解的注入

    对于DI使用注解,将不再需要在Spring配置文件中声明Bean实例.Spring中使用注解,需要在原有Spring运行环境基础上再做一些改变,完成以下三个步骤. (1)导入AOP的Jar包.因为注解 ...

  2. Ibatis,Spring整合(注解方式注入)

    applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans xm ...

  3. Spring中的注解配置-注入bean

    在使用Spring框架中@Autowired标签时默认情况下使用 @Autowired 注释进行自动注入时,Spring 容器中匹配的候选 Bean 数目必须有且仅有一个.当找不到一个匹配的 Bean ...

  4. Spring中@Autowired 注解的注入规则

    默认根据类型,匹配不到则根据bean名字 1.声明一个service接口 public interface HelloService { void sayHello(); } 2.service接口的 ...

  5. intellij安装lombok插件,解决注解@Slf4j注入后找不到变量log

    1.进入设置 2.搜索插件 3.安装

  6. Spring MVC常用注解

    cp by http://www.cnblogs.com/leskang/p/5445698.html 1.@Controller 在SpringMVC 中,控制器Controller 负责处理由Di ...

  7. spring mvc常用注解标签

    @Controller 在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model , ...

  8. spring : springmvc常用注解标签详解(转)

    新的项目,新的学习,好久没用这些注解了,同时在学习使用shiro ,lucene 等等.在网上找了些博文,感谢作者的总结和分享. 欢迎交流,言归正传: 1.@Controller 在SpringMVC ...

  9. Spring MVC学习总结(2)——Spring MVC常用注解说明

        使用Spring MVC的注解及其用法和其它相关知识来实现控制器功能. 02     之前在使用Struts2实现MVC的注解时,是借助struts2-convention这个插件,如今我们使 ...

随机推荐

  1. SAD DNS--新型DNS缓存中毒攻击

    一.DNS基础知识: 1.DNS简介: DNS 域名服务,用于建立 域名与 ip地址的 一对一 映射.DNS 将域名转换为 IP地址,以便浏览器能够加载 Internet 资源. 类似于一个翻译系统, ...

  2. Access数据库简介

    一.Access数据库的简介 1.microsoft office access是由微软发布的关联式数据库管理系统.它结合了 microsoft jet database engine 和 图形用户界 ...

  3. MockWebServer使用指南(转载)

    转载自(http://blog.csdn.net/shensky711/article/details/52771797 ) MockWebServer介绍 MockWebServer是square出 ...

  4. sql中count(1)、count(*)与count(列名)的区别

    1. count(1) and count(*) 当表的数据量大些时,对表作分析之后,使用count(1)还要比使用count(*)用时多了!从执行计划来看,count(1)和count(*)的效果是 ...

  5. Windows平台部署Asp.Net Core应用

    一. 简介 Asp.Net Core 部署方式有两种:依赖框架和独立部署. 1. 框架依赖的部署: 顾名思义,依赖框架的部署 (FDD) 依赖目标系统上存在共享系统级版本的 .NET Core. 由于 ...

  6. moviepy音视频剪辑:AudioClip帧处理时报TypeError: only size-1 arrays can be converted to Python scalar错

    ☞ ░ 前往老猿Python博文目录 ░ 一.环境 操作系统:win7 64位 moviepy:1.0.3 numpy:1.19.0 Python:3.7.2 二.应用代码及报错信息 程序代码 if ...

  7. 如何建一个SAM

    部分改编自OI WIKI 先从一个简单的问题入手: 给定一个串,构造一个图,使其能够表示它的所有子串. 显然一个子串就是一个后缀的前缀.所以一个很显然的方式就是把所有后缀扔进trie里. 比如当前串是 ...

  8. 题解-CF101D Castle

    题面 CF101D Castle 给一棵 \(n\) 个节点的带权树,求一种遍历方案,从 \(1\) 出发,每条边走两次,走过所有点,第一次经过每个节点的平均时间最小.输出这个平均时间. 数据范围:\ ...

  9. STL——容器(Map & multimap)的查找

    map.find(key);   //查找键key是否存在,若存在,返回该键的元素的迭代器:若不存在,返回map.end(); map.count(key);   //返回容器中键值为key的对组个数 ...

  10. Android原子操作——android_atomic_cmpxchg

    网络给我们带来了很多方便,查阅我们目前认知范围外的道理.但是,凡事也要学会分辨,不然可能会误导你. 话说,最近的一个项目(Mercury-Project),接近尾声中.然而,在调试一个demo时,却遇 ...