【问题标题】:How does bean self-auto-wiring work in Spring?bean 自自动装配在 Spring 中是如何工作的?
【发布时间】:2020-11-19 02:17:56
【问题描述】:

我最近在 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 应用程序上下文中有多少个对象副本?

与上一个问题有关,对象的实际副本有多少?

这是一个非常方便的功能,例如跨方法的事务,但我想知道幕后到底发生了什么。

【问题讨论】:

  • 只有一份。为什么会很难做到?创建一个实例并使用常规机制(用于字段注入的反射)将依赖关系设置为自身。这并不难,甚至不仅仅是 Spring EJB 和 CDI 可以做到这一点。如果你开始使用构造函数注入,事情就会变得棘手,因为你现在基本上对自己有一个循环依赖。

标签: java spring dependency-injection ioc-container


【解决方案1】:

如果您使用@Transactional、@Cachable 等注释,它不会注入 UserServiceImpl。它实际上会注入代理。

但作为基础,它使用相同的实例。

从 4.3 开始,@Autowired 还考虑注入的自引用(即,引用回当前注入的 bean)。请注意,自注入是一种后备。对其他组件的常规依赖始终具有优先权。从这个意义上说,自我参考不参与常规的候选人选择,因此尤其不是主要的。相反,它们总是以最低优先级结束。在实践中,您应该仅将自引用用作最后的手段(例如,通过 bean 的事务代理在同一实例上调用其他方法)。在这种情况下,考虑将受影响的方法分解为单独的委托 bean。或者,您可以使用@Resource,它可以通过其唯一名称获取返回到当前 bean 的代理。

【讨论】:

    【解决方案2】:
    • 只有一个副本,使用反射

    • 让我们看看这个示例

        @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() 是真的;

    【讨论】:

    • 另外注意,它不是注入代理。 spring 不需要创建代理
    猜你喜欢
    • 2011-03-10
    • 2022-08-20
    • 1970-01-01
    • 1970-01-01
    • 2011-01-23
    • 2012-07-14
    • 1970-01-01
    • 2022-09-23
    相关资源
    最近更新 更多