简体   繁体   English

spring 组件是否在未自动装配/注入时实例化?

[英]Are spring components instantiated when not autowired/injected?

I have a @Service that's injected into a conditional bean.我有一个注入到条件bean 中的@Service If the bean conditions is false , would the @Service be instantiated anyway?如果 bean 条件为false ,那么@Service是否会被实例化? Do I need to mark it @Lazy ?我需要标记它@Lazy吗?

Example:例子:

@Service
class MyService {
  public String doWork() {
    return "work";
  };
}
interface MyComponent {
  String handle();
}
@Component
@ConditionalOnProperty(value = "features.enabled", havingValue = "false", matchIfMissing = true)
class MyNoopComponent implements MyComponent {
  @Override
  public String handle() {
    return "";
  };
}
@Component
@ConditionalOnProperty(value = "features.enabled", havingValue = "true")
class MyDefaultComponent implements MyComponent {
  private final Service service;

  @Autowired
  MyDefaultComponent(MyService service) {
    this.service = service;
  }

  @Override
  public String handle() {
    return service.doWork();
  };
}
# application.yaml
features:
  enabled: false

I wouldn't recommend defining the MyService bean as lazy for the purpose you describe, as you either need the bean or you don't.我不建议出于您描述的目的将MyService bean 定义为惰性,因为您要么需要 bean,要么不需要。 And although eager instantiation on a lazy bean would be skipped when the feature is disabled, once the feature is enabled the first request requiring the bean would have to wait until the bean is fully instantiated.尽管在禁用该特性时会跳过对惰性 bean 的急切实例化,但一旦启用该特性,第一个需要该 bean 的请求将不得不等到该 bean 完全实例化。

Your ConditionalOnProperty works fine, why not apply it twice by adding it to the MyService as well?您的ConditionalOnProperty工作正常,为什么不通过将它添加到MyService来应用它两次呢? Or you can create your own meta-annotation to prevent having to duplicate the annotation's attributes:或者您可以创建自己的元注释以防止必须复制注释的属性:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ConditionalOnProperty(value = "features.enabled", havingValue = "true")
public @Interface ActiveWhenFeatureFlagEnabled {}
@Component
@ActiveWhenFeatureFlagEnabled
class MyDefaultComponent implements MyComponent { ... }
@Service
@ActiveWhenFeatureFlagEnabled
class MyService { ... }

I have a @Service that's injected into a conditional bean.我有一个注入到条件bean 中的@Service。 If the bean conditions is false, would the @Service be instantiated anyway?如果 bean 条件为假,@Service 是否会被实例化?

Yes, if you mark it as @Service and spring IOC container finds it during the startup (because it's a subject to component scanning) then it will load it, create the bean definition out of it, initialize the object, inject it's own dependencies and put onto the application context.是的,如果您将其标记为@Service并且 spring IOC 容器在启动期间找到它(因为它是组件扫描的对象)然后它将加载它,从中创建 bean 定义,初始化 object,注入它自己的依赖项并放到应用程序上下文中。 From this standpoint it doesn't matter whether the bean is injected into other beans or not.从这个角度来看,该 bean 是否被注入到其他 bean 中并不重要。

Do I need to mark it @Lazy?我需要标记它@Lazy 吗?

Usually lazy is used to "postpone" the initialization of bean till the point when its called first (read, its methods are invoked).通常lazy用于“推迟”bean的初始化,直到它第一次被调用(读取,它的方法被调用)。

If you do not call this bean's method - you basically do not need to create.如果你不调用这个bean的方法——你基本上不需要创建。 @Michiel already provided one way to avoid loading this bean with annotation, another method is "unify" all the relevant beans in java configuration: @Michiel 已经提供了一种避免使用注释加载此 bean 的方法,另一种方法是在 java 配置中“统一”所有相关 bean:

@Configuration
@ConditionalOnProperty(...)
public class MyConfig {

   @Bean
   public MyService myService() {
      return new MyService();
   }
   @Bean
   public MyDefaultComponent myDefaultComponent(MyService myService) {
        return new MyDefaultComponent(myService);
   }
}

This method allows specifying the conditional only once, so that if "tomorrow" you'll have even more beans to load - you'll know where to add them so that they will be loaded only upon certain value of your condition.此方法只允许指定条件一次,因此如果“明天”您将有更多的 bean 要加载 - 您将知道在哪里添加它们,以便它们仅在您的条件的某个值时加载。

Update 1更新 1

Roughly the same effect can be achieved by using a custom stereotype annotation See this tutorial for example使用自定义构造型注解可以达到大致相同的效果例如参见本教程

You can create your own annotation, say, @FeatureXService and annotated it with both @ConditionalOnProperty and regular @Service您可以创建自己的注释,例如@FeatureXService并使用@ConditionalOnProperty和常规@Service对其进行注释

Then you'll have to mark all the relevant beans with this annotation instead of regular @Service or @Component .然后,您必须使用此注释而不是常规的@Service@Component来标记所有相关的 bean。 The annotation looks like this:注释如下所示:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Service
@ConditionalOnProperty(name = "feature.x.enabled", havingValue = "true")
public @interface FeatureXService {
}

And the use it:并使用它:

@FeatureXService
class MyService {...}

@FeatureXService
class MyDefaultComponent implements MyComponent {...}

This also allows specifying the @ConditionalOnProperty only once.这也允许只指定一次@ConditionalOnProperty

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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