Incorrect injection between beans

2019-09-06 14:49发布

问题:

I am attempting create two beans for ldap connections.

In my context.xml file I create two LdapContextSource and then auto wire two beans with same parent class , derived like the PersonDao and PersonDaoImpl in the spring ldap examples.

The issue I keep getting is that both beans end up with the same context source. Even after I used @AutoWired @Qualifier .

The debug shows that both singleton beans see a different LdapContextSource but in the end both beans have same context.

Is there an example somewhere that demonstrates how to wire two ldap connections via context.xml and @autowired methodology?

I could do this just by programmatically assigning the ldapcontextsource in each class instance but I am trying to do this via @AutoWired.

Edited:

To make this clearer I paste some code samples from https://today.java.net/pub/a/today/2006/04/18/ldaptemplate-java-ldap-made-simple.html The beans to define the connection to ldap can be defined as follows:

<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>

Then the java class defined as:

public class PersonDaoImpl implements PersonDao {
   private LdapTemplate ldapTemplate;

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

Notice that I have two connections defined. One for ldap at port 389 and one for port 1389. Then I use the PersonDaoImpl twice.

Herein lies the problem.

The PersonDao2 gets the same connection at 389 as PersonDao NOT the 1389 it is suppose to get.

What can be causing this?

Edit 2:

Here is a portion of the log file where I think we can see the problem

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'

It seems to me that the relevant two lines are

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

and

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

Notice that both of these are getting

via property 'contextSource' to bean named 'contextSource'

The ldapTemplate2 should be getting:

via property 'contextSource' to bean named 'contextSource2'

Update: I was asked to provide the code I am using to wire into my class.

The first way was this:

@Controller
public class ManageAccountsController{
    private PersonDaoImpl personDao2;
}

using this way I got no initialization of personDao2

The second way was this:

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

The third way was this:

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

These last 2 methods I got the incorrect contextSource. The contextSource of personDao.

回答1:

oh okie..as i know @qualifier has some problem with constrcutor injection.. can you try single annotation @Resource(name="personDao2") instead of

 @Autowired
 @Qualifier("personDao2")

...let me know the result..



回答2:

So it sounds like you have wired your net.sf.ldaptemplate.LdapTemplate explicitly in xml, but then you also have an @Autowired annotation on the contextSource property in LdapTemplate, this I believe is the problem. I would recommend you go ahead and remove the @Autowired altogether on the LdapTemplate class, this way only the xml based wiring takes effect.



回答3:

I finally found the solution.

I had to explicitly define the contextSource such as

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