@Resource实战手册:七种场景搞定Spring依赖冲突,Spring依赖注入利器,掌握@Resource七种实战应用解决依赖冲突
场景一:多实现类引发的"选择困难症"
问题现场:咱们团队最近在开发支付模块,同时接入了微信和支付宝的SDK。两个支付处理器都实现了PaymentService接口,这时候@Autowired直接 *** 报错:
NoUniqueBeanDefinitionException: 发现两个实现类...
解决方案:掏出@Resource这把瑞士刀,在需要支付宝支付的控制器里这样写:
java复制@RestControllerpublic class OrderController {@Resource(name = "aliPaymentServiceImpl")private PaymentService paymentService; //精准锁定支付宝实现}
通过name属性直接指定Bean名称,就像在快递柜输入取件码一样精准。如果觉得写 *** 名称不优雅,可以在实现类上标注@Service("aliPay")
自定义别名。
场景二:祖传代码里的静态变量陷阱
问题现场:接手了一个老项目,发现工具类里这样写:
java复制public class FileUtils {@Resource //直接报错!private static StorageService storage;}
控制台疯狂输出:"@Resource不支持静态字段!"
正确姿势:用双重缓冲策略改造:
java复制@Componentpublic class FileUtils {private static StorageService staticStorage;@Resourceprivate StorageService tempStorage;@PostConstruct //项目启动时自动执行private void init() {staticStorage = this.tempStorage; //把动态bean赋给静态变量}}
这样既遵守了Spring的规则,又保留了静态调用的便利性。
场景三:混合框架的"水土不服"
问题现场:公司新项目要整合Spring和J2EE旧系统,用@Autowired注入的Bean在其他容器里总是null。
跨框架方案:改用JavaEE标准的@Resource注解:
java复制@Resource(lookup = "java:comp/env/jms/OrderQueue")private ConnectionFactory connectionFactory;
这就像给不同框架装了个转接头,通过JNDI名称定位资源,保证在WebLogic等容器中也能正常工作。
场景四:XML配置迁移的"阵痛期"
问题现场:领导要求把老旧的XML配置改为注解驱动,原来的bean引用是这样的:
xml复制<bean id="oldService" class="com.legacy.OldServiceImpl"/>
平滑迁移:分两步走:
- 在JavaConfig中声明Bean
java复制@Configurationpublic class AppConfig {@Bean("oldService") //保持原名public OldService oldService() {return new OldServiceImpl();}}
- 在业务类无缝切换
java复制@Servicepublic class NewService {@Resource(name = "oldService") //原来怎么用现在还怎么用private OldService dependency;}
这样既完成了技术升级,又避免了牵一发而动全身的风险。
场景五:循环依赖的" *** 亡缠绕"
问题现场:订单服务调用库存服务,库存服务又回调订单服务,启动时报BeanCurrentlyInCreationException。
破解之道:用@Resource的装配顺序特性:
java复制@Servicepublic class OrderService {@Resource //先按名称再按类型private StockService stockService; //库存服务此时可能还未初始化}@Servicepublic class StockService {@Lazy //延迟加载@Resourceprivate OrderService orderService;}
配合@Lazy注解打破循环枷锁,就像交通灯控制车流一样管理Bean的加载顺序。
场景六:多数据源的"分身术"
问题现场:系统要同时连接Oracle和MySQL数据库,直接@Autowired会报错:
找到两个DataSource类型的Bean
精准制导:在配置类定义不同数据源:
java复制@Configurationpublic class DataConfig {@Bean("oracleDS")public DataSource oracleDataSource() { ... }@Bean("mysqlDS")public DataSource mysqlDataSource() { ... }}
在DAO层按需调用:
java复制@Repositorypublic class ReportDao {@Resource(name = "oracleDS") //报表库用Oracleprivate DataSource reportDS;@Resource(name = "mysqlDS") //日志库用MySQLprivate DataSource logDS;}
这种方案比@Qualifier更直观,像给不同数据库贴了标签。
场景七:第三方jar包里的"神秘Bean"
问题现场:引入了一个加密工具包,里面有个自动配置的EncryptUtil,但@Autowired *** 活找不到。
外援接入:用@Resource的类型过滤功能:
java复制@Servicepublic class SecurityService {@Resource(type = EncryptUtil.class) //明确指定类型private EncryptUtil encryptor;}
即使这个Bean没有明确名称,也能通过类型精准捕获,就像用磁铁吸起水里的铁钉。
个人踩坑心得:用了五年@Resource,总结出三条铁律:
- 多实现必配name,少写一堆@Qualifier
- 静态变量要中转,@PostConstruct是钥匙
- 老项目改造慢慢来,name属性保平安
上次帮银行做系统迁移,就是靠着@Resource的name属性,三天就把300多个XML配置改成了注解驱动。现在看到复杂的依赖关系,反而有种解谜游戏的快感——毕竟解决问题的成就感,才是程序员的快乐源泉啊!