今日踩坑之@Autowired与@Resource区别
案例说明
今天算是体验到了这俩注解的区别了,真所谓不报错就记不住这两注解区别,其实之前本人也是知道这俩注解的区别的只是我们往往项目上用习惯了@Autowired就忘了,看来只有真正体会到报错才能记忆犹新o(╥﹏╥)o。
说明一下本人的踩坑情况,原本系统已经有一个BaseServiceBCMS类了,并且要注入到spring容器,现在我要创建一个新的BaseServiceBCMS60类也要注入容器,需要把原来使用BaseServiceBCMS类的代码全改为使用新的BaseServiceBCMS60类,因为当前改的是以前的老项目,大部分用的是@Resource,所以本人也是根据原来的也用@Resource,也可能是老项目的原因好家伙给我一个摸不着头脑的报错。
//原来注入的
@Resource
BaseServiceBCMS baseServiceBCMS;
本人改为下面,因为很多代码涉及用原来的baseServiceBCMS,我就把类型改为BaseServiceBCMS60 但是名字还是原来的,就能不用改关于baseServiceBCMS使用过的大量代码。
//原bcms
@Resource
BaseServiceBCMS baseServiceBCMSOld;
//新60服务器bcms
@Resource
BaseServiceBCMS60 baseServiceBCMS;
OK接下来这个报错真的...叫我去找问题??谁能想到是@Resource的问题。
09-Apr-2025 17:09:40.188 严重 [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.core.StandardContext.startInternal 一个或多个listeners启动失败,更多详细信息查看对应的容器日志文件
09-Apr-2025 17:09:40.190 严重 [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.core.StandardContext.startInternal 由于之前的错误,Context[/IDataFlowTomcat_war_exploded]启动失败
09-Apr-2025 17:09:40.223 警告 [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc Web应用程序 [IDataFlowTomcat_war_exploded] 注册了JDBC驱动程序 [com.alibaba.druid.proxy.DruidDriver],但在Web应用程序停止时无法注销它。 为防止内存泄漏,JDBC驱动程序已被强制取消注册。
09-Apr-2025 17:09:40.223 警告 [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc Web应用程序 [IDataFlowTomcat_war_exploded] 注册了JDBC驱动程序 [com.mysql.cj.jdbc.Driver],但在Web应用程序停止时无法注销它。 为防止内存泄漏,JDBC驱动程序已被强制取消注册。
[2025-04-09 05:09:40,237] 工件 IDataFlowTomcat:war exploded: 部署工件时出错。请参阅服务器日志了解详细信息。
09-Apr-2025 17:09:41.434 信息 [mysql-cj-abandoned-connection-cleanup] org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading 非法访问:此Web应用程序实例已停止。无法加载[]。为了调试以及终止导致非法访问的线程,将抛出以下堆栈跟踪。
java.lang.IllegalStateException: 非法访问:此Web应用程序实例已停止。无法加载[]。为了调试以及终止导致非法访问的线程,将抛出以下堆栈跟踪。
at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading(WebappClassLoaderBase.java:1435)
at org.apache.catalina.loader.WebappClassLoaderBase.getResource(WebappClassLoaderBase.java:1060)
at com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.checkThreadContextClassLoader(AbandonedConnectionCleanupThread.java:123)
at com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:90)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
本人一开始以为是数据库连接写错了,改了发现没用,然后又去看web.xml看了下监听器情况,发现没问题,最后通过代码一步步删除,才发现是 @Resource问题,可能是老项目报错不清楚的原因,真坑。最后又去温习了下@Autowired与@Resource区别,改成@Autowired成功运行。
@Autowired与@Resource区别
1.来源不同
注解 | 所属规范 |
@Autowired | spring框架 |
@Resource | java标准 |
2.注入方式不同
@Autowired
默认按照类型注入 (byType)
如果存在相同类型的bean,需要使用@Qualifier指定对应名称
@Autowired
@Qualifier("beanName")
private BcmsService service;
@Resource
默认按照名称注入(byName)
如果未指定名称name,先按字段/方法名查找,然后按类型查找
//原bcms
@Resource
BaseServiceBCMS baseServiceBCMSOld;
//新60服务器bcms
@Resource
BaseServiceBCMS60 baseServiceBCMS;
这里就是我错误的地方,因为baseServiceBCMS会先按名称查找,找到有BaseServiceBCMS 这个类但是我用的是BaseServiceBCMS60类型,导致报错。改为 @Autowired即可,因为@Autowired是先按类型查找或者改为@Resource(name="baseServiceBCMS60")指定name。
3.主要功能对比
特性 | @Autowired | @Resource |
是否必须注入依赖 | 是(可通过required=false设置为非必须) | 是(不可设置) |
是否支持构造器/方法注入 | 是 | 仅支持字段/setter注入 |
是否支持集合注入 | 是(注入所有匹配类型的bean) | 否 |
是否支持使用@primary | 是(优先使用@Primary 标注的Bean) | 否 |