@Resource注解JNDI名称不匹配仍注入资源的问题咨询
TomEE的资源注入机制默认会在找不到指定名称的资源时自动回退到类型匹配:当你用@Resource指定的名称(PROPERTIES)不存在时,容器会扫描所有同类型(javax.sql.DataSource)的可用资源,然后注入第一个匹配的实例(这里就是ID为DATA的数据源)。这是TomEE为简化开发提供的默认行为,但不符合你预期的"仅精确匹配"需求。
要实现仅精确匹配JNDI名称才注入(找不到则为null),可通过以下方式处理:
1. 使用lookup属性并设置required=false
将@Resource的name/mappedName替换为lookup属性,指定精确的JNDI路径,同时设置required=false,让容器仅查找指定的JNDI节点,找不到时注入null:
@Resource(lookup = "java:openejb/Resource/PROPERTIES", required = false) DataSource dataSource;
注:TomEE中配置的
<Resource id="PROPERTIES">默认绑定的JNDI路径是java:openejb/Resource/PROPERTIES;若资源为应用级配置(如web.xml内定义),路径可能是java:comp/env/PROPERTIES,可根据实际情况调整。
2. 全局禁用类型回退匹配
在TomEE的tomee.xml或应用内的openejb.xml中添加配置,强制容器仅按名称匹配:
<openejb> <!-- 开启仅按名称匹配,关闭类型回退逻辑 --> <Injector match-by-name-only="true"/> </openejb>
配置后所有@Resource注入都会严格匹配名称,找不到对应资源时,若设置required=false则注入null,否则抛出异常。
3. CDI精确匹配(可选)
若应用支持CDI,也可使用@Inject配合@Named和@Optional实现:
@Inject @Named("PROPERTIES") @Optional DataSource dataSource;
你的TomEE资源配置本身无错误,问题源于容器默认注入策略。上述方法均可实现"仅精确匹配"的需求,可根据应用场景选择使用。
内容的提问来源于stack exchange,提问作者Michael Neumair

