【问题标题】:Incorrect injection between beansbean之间的错误注入
【发布时间】:2014-06-10 07:42:20
【问题描述】:

我正在尝试为 ldap 连接创建两个 bean。

在我的 context.xml 文件中,我创建了两个 LdapContextSource ,然后自动连接两个具有相同父类的 bean,如 spring ldap 示例中的 PersonDao 和 PersonDaoImpl 派生的。

我不断遇到的问题是两个 bean 最终都具有相同的上下文源。即使在我使用 @AutoWired @Qualifier 之后。

调试显示两个单例 bean 看到不同的 LdapContextSource 但最终两个 bean 具有相同的上下文。

是否有示例演示如何通过 context.xml 和 @autowired 方法连接两个 ldap 连接?

我可以通过在每个类实例中以编程方式分配 ldapcontextsource 来做到这一点,但我试图通过 @AutoWired 做到这一点。

已编辑:

为了更清楚,我从https://today.java.net/pub/a/today/2006/04/18/ldaptemplate-java-ldap-made-simple.html 粘贴了一些代码示例 定义与 ldap 的连接的 bean 可以定义如下:

<beans>
   <context:annotation-config/>
   <context:component-scan base-package="the proper location of my code"/>
   <bean id="contextSource" class="net.sf.ldaptemplate.support.LdapContextSource">
      <property name="url" value="ldap://localhost:389" />
      <property name="base" value="dc=jayway,dc=se" />
      <property name="userName" value="cn=Manager" />
      <property name="password" value="secret" />
  </bean>

   <bean id="ldapTemplate" class="net.sf.ldaptemplate.LdapTemplate">
      <constructor-arg ref="contextSource" />
   </bean>

<bean id="personDao" class="se.jayway.dao.PersonDaoImpl">
    <property name="ldapTemplate" ref="ldapTemplate" />
</bean>

   <bean id="contextSource2" class="net.sf.ldaptemplate.support.LdapContextSource">
      <property name="url" value="ldap://localhost:1389" />
      <property name="base" value="dc=jayway,dc=se" />
      <property name="userName" value="cn=Manager" />
      <property name="password" value="secret" />
  </bean>

   <bean id="ldapTemplate2" class="net.sf.ldaptemplate.LdapTemplate">
      <constructor-arg ref="contextSource2" />
   </bean>

<bean id="personDao2" class="se.jayway.dao.PersonDaoImpl">
    <property name="ldapTemplate" ref="ldapTemplate2" />
</bean>

</beans>

那么java类定义为:

public class PersonDaoImpl implements PersonDao {
   private LdapTemplate ldapTemplate;

   public void setLdapTemplate(LdapTemplate ldapTemplate) {
      this.ldapTemplate = ldapTemplate;
   }
}

请注意,我定义了两个连接。一个用于 ldap 的 389 端口,一个用于 1389 端口。然后我使用 PersonDaoImpl 两次。

这就是问题所在。

PersonDao2 在 389 处获得与 PersonDao 相同的连接,而不是它应该获得的 1389。

是什么原因造成的?

编辑 2:

这是我认为我们可以看到问题的日志文件的一部分

DEBUG - Creating shared instance of singleton bean 'personDao'
DEBUG - Creating instance of bean 'personDao'
DEBUG - Eagerly caching bean 'personDao' to allow for resolving potential circular references
DEBUG - Creating shared instance of singleton bean 'ldapTemplate'
DEBUG - Creating instance of bean 'ldapTemplate'
DEBUG - Creating shared instance of singleton bean 'contextSource'
DEBUG - Creating instance of bean 'contextSource'
DEBUG - Eagerly caching bean 'contextSource' to allow for resolving potential circular references
DEBUG - Invoking afterPropertiesSet() on bean with name 'contextSource'
DEBUG - AuthenticationSource not set - using default implementation
DEBUG - Not using LDAP pooling
DEBUG - Trying provider Urls: ldap://xxx.xx.xx.158:389/dc=domain,dc=com
DEBUG - Returning cached instance of singleton bean 'org.springframework.security.methodSecurityMetadataSourceAdvisor'
DEBUG - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
DEBUG - Finished creating instance of bean 'contextSource'
DEBUG - Eagerly caching bean 'ldapTemplate' to allow for resolving potential circular references
DEBUG - Returning cached instance of singleton bean 'contextSource'
DEBUG - Added autowiring by name from bean name 'ldapTemplate' via property 'contextSource' to bean named 'contextSource'
DEBUG - Invoking afterPropertiesSet() on bean with name 'ldapTemplate'
DEBUG - Returning cached instance of singleton bean 'org.springframework.security.methodSecurityMetadataSourceAdvisor'
DEBUG - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
DEBUG - Finished creating instance of bean 'ldapTemplate'
DEBUG - Got Ldap context on server 'ldap://xxx.xx.xx.158:389/dc=domain,dc=com'
DEBUG - Entered setLdapTemplate getContextSource() getReadOnlyContext() dc=domain,dc=com
DEBUG - Entered setLdaptreepathminusroot ou=people
DEBUG - Returning cached instance of singleton bean 'org.springframework.security.methodSecurityMetadataSourceAdvisor'
DEBUG - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
DEBUG - Finished creating instance of bean 'personDao'
DEBUG - Creating shared instance of singleton bean 'PersonDao2'
DEBUG - Creating instance of bean 'PersonDao2'
DEBUG - Eagerly caching bean 'PersonDao2' to allow for resolving potential circular references
DEBUG - Creating shared instance of singleton bean 'ldapTemplate2'
DEBUG - Creating instance of bean 'ldapTemplate2'
DEBUG - Creating shared instance of singleton bean 'contextSource2'
DEBUG - Creating instance of bean 'contextSource2'
DEBUG - Eagerly caching bean 'contextSource2' to allow for resolving potential circular references
DEBUG - Invoking afterPropertiesSet() on bean with name 'contextSource2'
DEBUG - AuthenticationSource not set - using default implementation
DEBUG - Not using LDAP pooling
DEBUG - Trying provider Urls: ldap://xxx.xx.xx.147:389/dc=directory,dc=domain2,dc=com
DEBUG - Returning cached instance of singleton bean 'org.springframework.security.methodSecurityMetadataSourceAdvisor'
DEBUG - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
DEBUG - Finished creating instance of bean 'contextSource2'
DEBUG - Eagerly caching bean 'ldapTemplate2' to allow for resolving potential circular references
DEBUG - Returning cached instance of singleton bean 'contextSource'
DEBUG - Added autowiring by name from bean name 'ldapTemplate2' via property 'contextSource' to bean named 'contextSource'
DEBUG - Invoking afterPropertiesSet() on bean with name 'ldapTemplate2'
DEBUG - Returning cached instance of singleton bean 'org.springframework.security.methodSecurityMetadataSourceAdvisor'
DEBUG - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
DEBUG - Finished creating instance of bean 'ldapTemplate2'
DEBUG - Got Ldap context on server 'ldap://xxx.xx.xx.158:389/dc=domain,dc=com'
DEBUG - Entered setLdapTemplate getContextSource() getReadOnlyContext() dc=domain,dc=com
DEBUG - Entered setLdaptreepathminusroot ou=individualprovider
DEBUG - Returning cached instance of singleton bean 'org.springframework.security.methodSecurityMetadataSourceAdvisor'
DEBUG - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
DEBUG - Finished creating instance of bean 'PersonDao2'

在我看来,相关的两行是

DEBUG - Added autowiring by name from bean name 'ldapTemplate' via property  'contextSource' to bean named 'contextSource'

DEBUG - Added autowiring by name from bean name 'ldapTemplate2' via property 'contextSource' to bean named 'contextSource'

请注意,这两个都得到了

via property 'contextSource' to bean named 'contextSource'

ldapTemplate2 应该得到:

via property 'contextSource' to bean named 'contextSource2'

更新: 我被要求提供我用来连接到我的班级的代码。

第一种方法是这样的:

@Controller
public class ManageAccountsController{
    private PersonDaoImpl personDao2;
}

使用这种方式我没有初始化 personDao2

第二种方式是这样的:

@Controller
public class ManageAccountsController{
    @Autowired PersonDaoImpl personDao2;
}

第三种方式是这样的:

@Controller
public class ManageAccountsController{
    @Autowired @Qualifier("personDao2") PersonDaoImpl personDao2;
}

这最后 2 种方法我得到了不正确的 contextSource。 personDao 的 contextSource。

【问题讨论】:

  • 你能说明你是如何为 DAO2 自动装配的吗?
  • 我已更新问题以显示 DAO2 的接线方式。
  • 第二种方式你没有得到异常......因为自动装配是按类型发生的,但它有多个该类型?
  • 正确。没有例外。我同意你的意见。这就是为什么我添加了@Qualifier

标签: spring spring-mvc spring-ldap


【解决方案1】:

哦,好吧..据我所知@qualifier 构造函数注入有一些问题.. 您可以尝试使用单个注释@Resource(name="personDao2") 而不是

 @Autowired
 @Qualifier("personDao2")

...让我知道结果..

【讨论】:

  • 感谢您的帮助。我按问题更新以包括注释配置以及组件扫描。我的代码中已经有了这些,只是没有在我的问题中定义它们。我仍然有同样的问题。
  • 谢谢。我替换为@Resource(name="personDao2") 结果是上下文仍然指向错误的ip地址。
【解决方案2】:

所以听起来你已经在 xml 中明确地连接了你的net.sf.ldaptemplate.LdapTemplate,但是你在LdapTemplatecontextSource 属性上也有一个@Autowired 注释,我相信这是问题所在。我建议您继续在LdapTemplate 类上完全删除@Autowired,这样只有基于xml 的接线才会生效。

【讨论】:

  • 感谢您的帮助。我对你的回答深思熟虑。我已将我的问题编辑为我尝试过的 3 种方法。你的回答确实有道理,但由于某种原因,我一直得到一个空值。对象未初始化。
  • 我已经证实 ldapcontextsource 是罪魁祸首。不知何故,即使我在 xml 中设置它,它也没有得到正确的 url。
【解决方案3】:

我终于找到了解决办法。

我必须明确定义 contextSource 例如

<bean id="ldapTemplate2" class="net.sf.ldaptemplate.LdapTemplate">
    <property name="contextSource" ref="contextSource2" />
</bean>

【讨论】:

  • 是的,我怀疑 constrcutor 和 qualifer 有问题,甚至我在回答中也提到过……反正现在很好……
  • 再次感谢您的帮助和帮助。我很感激
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-03
  • 2014-03-19
  • 1970-01-01
  • 2022-07-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多