Spring 中 bean 的自动装配是如何工作的?
How does bean self-auto-wiring work in Spring?
我最近在 Spring 中发现的一个非常酷而且令人难以置信的功能是 self auto-wiring a bean。
我指的是这个:
class UserServiceImpl implements UserService {
@Autowired
UserService service;
// other service methods...
}
我的问题如下:
- 这是如何实现的?
Spring 如何管理这个?它是否将相同的对象分配给自自动连接引用?像这样:
UserServiceImpl serviceImpl = new UserServiceImpl();
serviceImpl.setService(serviceImpl); // Obviously this would be done via Reflection rather than a setter.
或
Spring 会制作 2 个单独的对象吗?像这样:
UserServiceImpl obj1 = new UserServiceImpl();
UserServiceImpl obj2 = new UserServiceImpl();
obj1.setService(obj2);
当我们在 RestController
中请求时,只给我们 obj1
?
- Spring 应用程序上下文中有多少个对象副本?
与上一个问题相关,对象的实际副本有多少?
对于跨方法事务之类的事情,这是一个非常方便的功能,但我想知道这里到底发生了什么。
只有一份并且使用了反射
让我们看看这个示例
@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());
}
}
- 如您所见
sampleService == sampleService.getService()
为真;
如果您使用@Transactional、@Cachable 等注释,它不会注入 UserServiceImpl。它实际上会注入代理。
但作为基础,它使用相同的实例。
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.
我最近在 Spring 中发现的一个非常酷而且令人难以置信的功能是 self auto-wiring a bean。
我指的是这个:
class UserServiceImpl implements UserService {
@Autowired
UserService service;
// other service methods...
}
我的问题如下:
- 这是如何实现的?
Spring 如何管理这个?它是否将相同的对象分配给自自动连接引用?像这样:
UserServiceImpl serviceImpl = new UserServiceImpl();
serviceImpl.setService(serviceImpl); // Obviously this would be done via Reflection rather than a setter.
或
Spring 会制作 2 个单独的对象吗?像这样:
UserServiceImpl obj1 = new UserServiceImpl();
UserServiceImpl obj2 = new UserServiceImpl();
obj1.setService(obj2);
当我们在 RestController
中请求时,只给我们 obj1
?
- Spring 应用程序上下文中有多少个对象副本?
与上一个问题相关,对象的实际副本有多少?
对于跨方法事务之类的事情,这是一个非常方便的功能,但我想知道这里到底发生了什么。
只有一份并且使用了反射
让我们看看这个示例
@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());
}
}
- 如您所见
sampleService == sampleService.getService()
为真;
如果您使用@Transactional、@Cachable 等注释,它不会注入 UserServiceImpl。它实际上会注入代理。
但作为基础,它使用相同的实例。
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.