Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define and document rules for @Autowired self-injection in case of ambiguity [SPR-14402] #18973

Closed
spring-projects-issues opened this issue Jun 26, 2016 · 1 comment
Assignees
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

@spring-projects-issues spring-projects-issues commented Jun 26, 2016

Sam Brannen opened SPR-14402 and commented

Status Quo

The support for self-injection via @Autowired introduced in #13096 works as expected if there is a single candidate bean; however, as soon as there is more than one such candidate self-injection becomes unreliable.

  1. @Primary and @Priority have no influence, in contrast to standard autowiring semantics.
  2. Field names do not serve as a fallback qualifier, in contrast to standard autowiring semantics.
  3. The only work-around appears to be the use of @Qualifier for every self-injection point.

Steps to Reproduce

The following test case can be used to experiment with all of the aforementioned failure scenarios.

Running SelfInjectionTests as is in fact demonstrates that each self field consistently contains the other bean of type UserService.

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {
	SelfInjectionTests.UserServiceImpl1.class,
	SelfInjectionTests.UserServiceImpl2.class
})
public class SelfInjectionTests {

	@Autowired
	@Qualifier("userService1")
	UserService userService1;

	@Autowired
	@Qualifier("userService2")
	UserService userService2;

	@Test
	public void selfInjection1() {
		assertSame(userService1, userService1.getSelf());
	}

	@Test
	public void selfInjection2() {
		assertSame(userService2, userService2.getSelf());
	}

	interface UserService {
		UserService getSelf();
	}

	@Service("userService1")
	@Primary
	static class UserServiceImpl1 implements UserService {

		@Autowired
		// @Qualifier("userService1")
		private UserService userService1;

		public UserService getSelf() {
			return this.userService1;
		}

		@Override
		public String toString() {
			return "userService1";
		}
	}

	@Service("userService2")
	static class UserServiceImpl2 implements UserService {

		@Autowired
		// @Qualifier("userService2")
		private UserService userService2;

		public UserService getSelf() {
			return this.userService2;
		}

		@Override
		public String toString() {
			return "userService2";
		}
	}
}

Affects: 4.3 GA

Issue Links:

  • #13096 Support @Autowired-like self injection

Referenced from: commits c6752e6

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 26, 2016

Juergen Hoeller commented

Self injection is indeed implemented as a kind of secondary step, with regular dependencies on other components having precedence. In that sense, self references are never primary; on the contrary, they always end up as lowest precedence.

The use of field names for qualifiers is indeed debatable here. The primary reason for this not to happen is backwards compatibility: We avoid injecting a self reference where we would have cleanly injected a regular dependency before.

In any case, this needs to be clearly defined and documented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants