[英]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.