简体   繁体   中英

How does bean self-auto-wiring work in Spring?

One of the really cool and rather mind boggling features that I have recently discovered in Spring is self auto-wiring a bean .

What I am referring to is this:

class UserServiceImpl implements UserService {

    @Autowired
    UserService service;

    // other service methods...
}

My questions are as follows:

  • How is this implemented?

How does Spring manage this? Does it assign the same object to self auto-wire reference? Like so:

UserServiceImpl serviceImpl = new UserServiceImpl();
serviceImpl.setService(serviceImpl); // Obviously this would be done via Reflection rather than a setter.

or

does Spring make 2 seperate objects? Like so:

UserServiceImpl obj1 = new UserServiceImpl();
UserServiceImpl obj2 = new UserServiceImpl();

obj1.setService(obj2);

And just gives us obj1 when we request it in a RestController ?

  • How many copies of the object are there in the Spring Application Context?

Related to the previous question, how many actual copies of the object are there?

Its a very convenient feature for things like transactions across methods, but I want to know what is exactly going on behind the scenes here.

  • There is only one copy and uses reflection

  • Lets look at this sample

    @Service
    public class SampleService {
    
        @Autowired
        private SampleService service;
    
        public SampleService getService() {
            return service;
        }
    }
    @SpringBootApplication
    public class RestServiceApplication {

      public static void main(String[] args) {
        ConfigurableApplicationContext context
                = SpringApplication.run(RestServiceApplication.class, args);
        SampleService sampleService = context.getBean(SampleService.class);
        //This will print true
        System.out.println(sampleService == sampleService.getService());
      }
    }
  • As you can see sampleService == sampleService.getService() is true;

It doesn't inject the UserServiceImpl if you use some annotation like @Transactional,@Cachable etc. It actually injects the proxy.

But as the base it uses the same instance.

As of 4.3, @Autowired also considers self references for injection (that is, references back to the bean that is currently injected). Note that self injection is a fallback. Regular dependencies on other components always have precedence. In that sense, self references do not participate in regular candidate selection and are therefore in particular never primary. On the contrary, they always end up as lowest precedence. In practice, you should use self references as a last resort only (for example, for calling other methods on the same instance through the bean's transactional proxy). Consider factoring out the affected methods to a separate delegate bean in such a scenario. Alternatively, you can use @Resource, which may obtain a proxy back to the current bean by its unique name.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM