1.10. Classpath Scanning and Managed Components

类路径扫描和托管组件

Most examples in this chapter use XML to specify the configuration metadata that produces each BeanDefinition within the Spring container. The previous section (Annotation-based Container Configuration) demonstrates how to provide a lot of the configuration metadata through source-level annotations. Even in those examples, however, the “base” bean definitions are explicitly defined in the XML file, while the annotations drive only the dependency injection. This section describes an option for implicitly detecting the candidate components by scanning the classpath. Candidate components are classes that match against a filter criteria and have a corresponding bean definition registered with the container. This removes the need to use XML to perform bean registration. Instead, you can use annotations (for example, @Component), AspectJ type expressions, or your own custom filter criteria to select which classes have bean definitions registered with the container.

本章中的大多数示例都使用 XML 来指定BeanDefinition在 Spring 容器中生成的配置元数据。上一节(基于注解的容器配置) 演示如何通过源级注释提供大量配置元数据。然而,即使在这些示例中,“基本”bean 定义也在 XML 文件中明确定义,而注释仅驱动依赖注入。本节描述了通过扫描类路径隐式检测候选组件的选项。候选组件是与过滤条件匹配的类,并在容器中注册了相应的 bean 定义。这消除了使用 XML 来执行 bean 注册的需要。相反,您可以使用注解(例如@Component)、AspectJ 类型表达式或您自己的自定义过滤条件来选择哪些类具有向容器注册的 bean 定义。

Starting with Spring 3.0, many features provided by the Spring JavaConfig project are part of the core Spring Framework. This allows you to define beans using Java rather than using the traditional XML files. Take a look at the @Configuration, @Bean, @Import, and @DependsOn annotations for examples of how to use these new features.
从 Spring 3.0 开始,Spring JavaConfig 项目提供的许多特性都是核心 Spring Framework 的一部分。这允许您使用 Java 而不是使用传统的 XML 文件来定义 bean。查看@Configuration@Bean@Import@DependsOn注释,了解如何使用这些新功能的示例。

1.10.1. @Component and Further Stereotype Annotations

@Component和进一步的模板注释

The @Repository annotation is a marker for any class that fulfills the role or stereotype of a repository (also known as Data Access Object or DAO). Among the uses of this marker is the automatic translation of exceptions, as described in Exception Translation.

@Repository注释是满足存储库(也称为数据访问对象或 DAO)角色或原型的任何类的标记。此标记的用途之一是异常的自动翻译,如 Exception Translation中所述。

Spring provides further stereotype annotations: @Component, @Service, and @Controller. @Component is a generic stereotype for any Spring-managed component. @Repository, @Service, and @Controller are specializations of @Component for more specific use cases (in the persistence, service, and presentation layers, respectively). Therefore, you can annotate your component classes with @Component, but, by annotating them with @Repository, @Service, or @Controller instead, your classes are more properly suited for processing by tools or associating with aspects. For example, these stereotype annotations make ideal targets for pointcuts. @Repository, @Service, and @Controller can also carry additional semantics in future releases of the Spring Framework. Thus, if you are choosing between using @Component or @Service for your service layer, @Service is clearly the better choice. Similarly, as stated earlier, @Repository is already supported as a marker for automatic exception translation in your persistence layer.

Spring 提供了更多的原型注解:@Component@Service@Controller. @Component是任何 Spring 管理的组件的通用构造型。 @Repository, @Service, 和@Controller@Component针对更具体用例(分别在持久层、服务层和表示层)的特化。因此,您可以使用 注释组件类 @Component,但是通过使用 、 注释它们@Repository@Service或者@Controller 相反,您的类更适合工具处理或与方面关联。例如,这些原型注释是切入点的理想目标。@Repository, @Service, 并且@Controller还可以在 Spring 框架的未来版本中携带额外的语义。因此,如果您在使用@Component或者@Service对于你的服务层,@Service显然是更好的选择。同样,如前所述,@Repository已经支持作为持久层中自动异常转换的标记。

1.10.2. Using Meta-annotations and Composed Annotations

使用元注释和组合注释

Many of the annotations provided by Spring can be used as meta-annotations in your own code. A meta-annotation is an annotation that can be applied to another annotation. For example, the @Service annotation mentioned earlier is meta-annotated with @Component, as the following example shows:

Spring提供的许多注释可以在您自己的代码中用作元注释。元注释是可以应用于其他注释的注释。例如,[前面]提到的“@Service”注释,用“@Component”进行元注释,如下例所示:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {// ...
}
The @Component causes @Service to be treated in the same way as @Component.
@Component导致以与@Component相同的方式处理@Service。

You can also combine meta-annotations to create “composed annotations”. For example, the @RestController annotation from Spring MVC is composed of @Controller and @ResponseBody.

您还可以组合元注释来创建“组合注释”。例如,@RestControllerSpring MVC 的注解由@Controller和 组成@ResponseBody

In addition, composed annotations can optionally redeclare attributes from meta-annotations to allow customization. This can be particularly useful when you want to only expose a subset of the meta-annotation’s attributes. For example, Spring’s @SessionScope annotation hardcodes the scope name to session but still allows customization of the proxyMode. The following listing shows the definition of the SessionScope annotation:

此外,组合注释可以选择从元注释中重新声明属性以允许自定义。当您只想公开元注释属性的子集时,这可能特别有用。例如,Spring 的 @SessionScope注解将作用域名称硬编码为,session但仍允许自定义proxyMode. 以下清单显示了 SessionScope注释的定义:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Scope(WebApplicationContext.SCOPE_SESSION)
public @interface SessionScope {/*** Alias for {@link Scope#proxyMode}.* <p>Defaults to {@link ScopedProxyMode#TARGET_CLASS}.*/@AliasFor(annotation = Scope.class)ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
}

You can then use @SessionScope without declaring the proxyMode as follows:

然后,您可以在@SessionScope不声明proxyMode如下的情况下使用:

@Service
@SessionScope
public class SessionScopedService {// ...
}

You can also override the value for the proxyMode, as the following example shows:

您还可以覆盖proxyMode的值,如以下示例所示:

@Service
@SessionScope(proxyMode = ScopedProxyMode.INTERFACES)
public class SessionScopedUserService implements UserService {// ...
}

For further details, see the Spring Annotation Programming Model wiki page.

有关更多详细信息,请参阅 Spring Annotation Programming Model wiki 页面。

1.10.3. Automatically Detecting Classes and Registering Bean Definitions

自动检测类和注册 Bean 定义

Spring can automatically detect stereotyped classes and register corresponding BeanDefinition instances with the ApplicationContext. For example, the following two classes are eligible for such autodetection:

Spring 可以自动检测原型类并 BeanDefinition使用ApplicationContext. 例如,以下两个类有资格进行此类自动检测:

@Service
public class SimpleMovieLister {private MovieFinder movieFinder;public SimpleMovieLister(MovieFinder movieFinder) {this.movieFinder = movieFinder;}
}
@Repository
public class JpaMovieFinder implements MovieFinder {// implementation elided for clarity
}

To autodetect these classes and register the corresponding beans, you need to add @ComponentScan to your @Configuration class, where the basePackages attribute is a common parent package for the two classes. (Alternatively, you can specify a comma- or semicolon- or space-separated list that includes the parent package of each class.)

要自动检测这些类并注册相应的 bean,您需要添加 @ComponentScan到您的@Configuration类中,其中basePackages属性是两个类的公共父包。(或者,您可以指定一个逗号或分号或空格分隔的列表,其中包括每个类的父包。)

@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {// ...
}
For brevity, the preceding example could have used the value attribute of the annotation (that is, @ComponentScan("org.example")).
为简洁起见,前面的示例可能使用value了注释的属性(即@ComponentScan("org.example"))。

The following alternative uses XML:

以下替代方法使用 XML:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="org.example"/>
</beans>
The use of <context:component-scan> implicitly enables the functionality of <context:annotation-config>. There is usually no need to include the <context:annotation-config> element when using <context:component-scan>.
使用<context:component-scan>隐式启用 <context:annotation-config>. 使用时通常不需要包含该 <context:annotation-config>元素<context:component-scan>
The scanning of classpath packages requires the presence of corresponding directory entries in the classpath. When you build JARs with Ant, make sure that you do not activate the files-only switch of the JAR task. Also, classpath directories may not be exposed based on security policies in some environments — for example, standalone apps on JDK 1.7.0_45 and higher (which requires 'Trusted-Library' setup in your manifests — see java jre 7u45 breaks classloader.getResources()? - Stack Overflow JDK 9’s module path (Jigsaw), Spring’s classpath scanning generally works as expected. However, make sure that your component classes are exported in your module-info descriptors. If you expect Spring to invoke non-public members of your classes, make sure that they are 'opened' (that is, that they use an opens declaration instead of an exports declaration in your module-info descriptor).
类路径包的扫描需要类路径中存在相应的目录条目。当您使用 Ant 构建 JAR 时,请确保您没有激活 JAR 任务的仅文件开关。此外,在某些环境中,类路径目录可能不会根据安全策略公开——例如,JDK 1.7.0_45 及更高版本上的独立应用程序(这需要在清单中设置“Trusted-Library”——请参阅 https://stackoverflow.com/问题/19394570/java-jre-7u45-breaks-classloader-getresources)。在 JDK 9 的模块路径(Jigsaw)上,Spring 的类路径扫描通常按预期工作。但是,请确保您的组件类在您的module-info 描述符中导出。如果您希望 Spring 调用类的非公共成员,请确保它们是“打开的”(即,它们使用opens声明而不是描述符中的 exports声明module-info)。

Furthermore, the AutowiredAnnotationBeanPostProcessor and CommonAnnotationBeanPostProcessor are both implicitly included when you use the component-scan element. That means that the two components are autodetected and wired together — all without any bean configuration metadata provided in XML.

此外,当您使用 component-scan 元素时, AutowiredAnnotationBeanPostProcessorand CommonAnnotationBeanPostProcessor都被隐式包含在内。这意味着这两个组件会被自动检测并连接在一起——所有这些都不需要 XML 中提供任何 bean 配置元数据。

You can disable the registration of AutowiredAnnotationBeanPostProcessor and CommonAnnotationBeanPostProcessor by including the annotation-config attribute with a value of false.
您可以禁用注册AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor通过包含annotation-config值为 false的属性。

1.10.4. Using Filters to Customize Scanning

使用过滤器自定义扫描

By default, classes annotated with @Component, @Repository, @Service, @Controller, @Configuration, or a custom annotation that itself is annotated with @Component are the only detected candidate components. However, you can modify and extend this behavior by applying custom filters. Add them as includeFilters or excludeFilters attributes of the @ComponentScan annotation (or as <context:include-filter /> or <context:exclude-filter /> child elements of the <context:component-scan> element in XML configuration). Each filter element requires the type and expression attributes. The following table describes the filtering options:

默认情况下,仅检测到使用“@Component”、“Repository”、“Service”、“Controller”、“Configuration”注释的类,或使用“@Component”注释的自定义注释。但是,您可以通过应用自定义过滤器来修改和扩展此行为。将它们添加为“@ComponentScan”注释的“includeFilters”或“excludeFilters”属性(或作为XML配置中“<context:component scan”元素的子元素“<context:include filter/>”或“<context:exclude filter/>”)。每个过滤器元素都需要“type”和“expression”属性。下表介绍了过滤选项:

Filter Type Example Expression Description
annotation (default) org.example.SomeAnnotation An annotation to be present or meta-present at the type level in target components.
在目标组件的类型级别存在元存在的注释。
assignable org.example.SomeClass A class (or interface) that the target components are assignable to (extend or implement).
目标组件可分配(扩展或实现)的类(或接口)。
aspectj org.example..*Service+ An AspectJ type expression to be matched by the target components.
要由目标组件匹配的 AspectJ 类型表达式。
regex org\.example\.Default.* A regex expression to be matched by the target components' class names.
与目标组件的类名匹配的正则表达式。
custom org.example.MyTypeFilter A custom implementation of the org.springframework.core.type.TypeFilter interface.
接口的自定义实现org.springframework.core.type.TypeFilter

The following example shows the configuration ignoring all @Repository annotations and using “stub” repositories instead:

以下示例显示了忽略所有@Repository注释并使用“存根”存储库的配置:

@Configuration
@ComponentScan(basePackages = "org.example",includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),excludeFilters = @Filter(Repository.class))
public class AppConfig {// ...
}

The following listing shows the equivalent XML:

以下清单显示了等效的 XML:

<beans><context:component-scan base-package="org.example"><context:include-filter type="regex"expression=".*Stub.*Repository"/><context:exclude-filter type="annotation"expression="org.springframework.stereotype.Repository"/></context:component-scan>
</beans>
You can also disable the default filters by setting useDefaultFilters=false on the annotation or by providing use-default-filters="false" as an attribute of the <component-scan/> element. This effectively disables automatic detection of classes annotated or meta-annotated with @Component, @Repository, @Service, @Controller, @RestController, or @Configuration.
您还可以通过useDefaultFilters=false在注释上设置或use-default-filters="false"作为 <component-scan/>元素的属性提供来禁用默认过滤器。@Component这有效地禁用了用, @Repository, @Service, @Controller, @RestController, 或注释或元注释的类的自动检测@Configuration

1.10.5. Defining Bean Metadata within Components

在组件中定义 Bean 元数据

Spring components can also contribute bean definition metadata to the container. You can do this with the same @Bean annotation used to define bean metadata within @Configuration annotated classes. The following example shows how to do so:

Spring 组件还可以将 bean 定义元数据贡献给容器。您可以使用用于在带 注释的类@Bean中定义 bean 元数据的相同注释来执行此操作。@Configuration以下示例显示了如何执行此操作:

@Component
public class FactoryMethodComponent {@Bean@Qualifier("public")public TestBean publicInstance() {return new TestBean("publicInstance");}public void doWork() {// Component method implementation omitted}
}

The preceding class is a Spring component that has application-specific code in its doWork() method. However, it also contributes a bean definition that has a factory method referring to the method publicInstance(). The @Bean annotation identifies the factory method and other bean definition properties, such as a qualifier value through the @Qualifier annotation. Other method-level annotations that can be specified are @Scope, @Lazy, and custom qualifier annotations.

前面的类是一个 Spring 组件,它的 doWork()方法中包含特定于应用程序的代码。但是,它还提供了一个 bean 定义,该定义具有引用方法的工厂方法publicInstance()@Bean注释标识工厂方法和其他 bean 定义属性,例如通过注释的限定符值@Qualifier。可以指定的其他方法级注释是 @Scope,@Lazy和自定义限定符注释。

In addition to its role for component initialization, you can also place the @Lazy annotation on injection points marked with @Autowired or @Inject. In this context, it leads to the injection of a lazy-resolution proxy. However, such a proxy approach is rather limited. For sophisticated lazy interactions, in particular in combination with optional dependencies, we recommend ObjectProvider<MyTargetBean> instead.
除了它在组件初始化中的作用外,您还可以将“Lazy”注释放置在标有“Autowired”或“Inject”的注入点上。在这种情况下,它会引入延迟解析代理。然而,这种代理方法相当有限。对于复杂的延迟交互,特别是与可选依赖项相结合,我们建议改为“ObjectProvider<MyTargetBean>”。

Autowired fields and methods are supported, as previously discussed, with additional support for autowiring of @Bean methods. The following example shows how to do so:

如前所述,支持自动装配的字段和方法,并额外支持@Bean方法的自动装配。以下示例显示了如何执行此操作:

@Component
public class FactoryMethodComponent {private static int i;@Bean@Qualifier("public")public TestBean publicInstance() {return new TestBean("publicInstance");}// use of a custom qualifier and autowiring of method parameters@Beanprotected TestBean protectedInstance(@Qualifier("public") TestBean spouse,@Value("#{privateInstance.age}") String country) {TestBean tb = new TestBean("protectedInstance", 1);tb.setSpouse(spouse);tb.setCountry(country);return tb;}@Beanprivate TestBean privateInstance() {return new TestBean("privateInstance", i++);}@Bean@RequestScopepublic TestBean requestScopedInstance() {return new TestBean("requestScopedInstance", 3);}
}

The example autowires the String method parameter country to the value of the age property on another bean named privateInstance. A Spring Expression Language element defines the value of the property through the notation #{ <expression> }. For @Value annotations, an expression resolver is preconfigured to look for bean names when resolving expression text.

该示例将“String”方法参数“country”自动关联到另一个名为“privateInstance”的bean的“age”属性的值。Spring表达式语言元素通过符号#{<Expression>}定义属性的值。对于“@Value”注释,表达式解析器被预配置为在解析表达式文本时查找bean名称。

As of Spring Framework 4.3, you may also declare a factory method parameter of type InjectionPoint (or its more specific subclass: DependencyDescriptor) to access the requesting injection point that triggers the creation of the current bean. Note that this applies only to the actual creation of bean instances, not to the injection of existing instances. As a consequence, this feature makes most sense for beans of prototype scope. For other scopes, the factory method only ever sees the injection point that triggered the creation of a new bean instance in the given scope (for example, the dependency that triggered the creation of a lazy singleton bean). You can use the provided injection point metadata with semantic care in such scenarios. The following example shows how to use InjectionPoint:

从 Spring Framework 4.3 开始,您还可以声明类型 InjectionPoint(或其更具体的子类:)的工厂方法参数DependencyDescriptor来访问触发当前 bean 创建的请求注入点。请注意,这仅适用于 bean 实例的实际创建,不适用于现有实例的注入。因此,此功能对于原型范围的 bean 最有意义。对于其他范围,工厂方法只看到在给定范围内触发创建新 bean 实例的注入点(例如,触发创建惰性单例 bean 的依赖项)。在这种情况下,您可以使用提供的带有语义关怀的注入点元数据。下面的例子展示了如何使用InjectionPoint

@Component
public class FactoryMethodComponent {@Bean @Scope("prototype")public TestBean prototypeInstance(InjectionPoint injectionPoint) {return new TestBean("prototypeInstance for " + injectionPoint.getMember());}
}

The @Bean methods in a regular Spring component are processed differently than their counterparts inside a Spring @Configuration class. The difference is that @Component classes are not enhanced with CGLIB to intercept the invocation of methods and fields. CGLIB proxying is the means by which invoking methods or fields within @Bean methods in @Configuration classes creates bean metadata references to collaborating objects. Such methods are not invoked with normal Java semantics but rather go through the container in order to provide the usual lifecycle management and proxying of Spring beans, even when referring to other beans through programmatic calls to @Bean methods. In contrast, invoking a method or field in a @Bean method within a plain @Component class has standard Java semantics, with no special CGLIB processing or other constraints applying.

常规 Spring 组件中的方法的处理方式与 Spring类中@Bean的对应方法不同。@Configuration不同之处在于@Component 类没有通过 CGLIB 增强来拦截方法和字段的调用。CGLIB 代理是调用类@Bean方法中的方法或字段@Configuration创建协作对象的 bean 元数据引用的方法。这样的方法不是用普通的 Java 语义调用的,而是通过容器来提供 Spring bean 的通常的生命周期管理和代理,即使通过对@Bean方法的编程调用来引用其他 bean 也是如此。相反,在@Bean普通的方法中调用方法或字段@Component 类具有标准的 Java 语义,没有特殊的 CGLIB 处理或其他应用约束。

You may declare @Bean methods as static, allowing for them to be called without creating their containing configuration class as an instance. This makes particular sense when defining post-processor beans (for example, of type BeanFactoryPostProcessor or BeanPostProcessor), since such beans get initialized early in the container lifecycle and should avoid triggering other parts of the configuration at that point.Calls to static @Bean methods never get intercepted by the container, not even within @Configuration classes (as described earlier in this section), due to technical limitations: CGLIB subclassing can override only non-static methods. As a consequence, a direct call to another @Bean method has standard Java semantics, resulting in an independent instance being returned straight from the factory method itself.The Java language visibility of @Bean methods does not have an immediate impact on the resulting bean definition in Spring’s container. You can freely declare your factory methods as you see fit in non-@Configuration classes and also for static methods anywhere. However, regular @Bean methods in @Configuration classes need to be overridable — that is, they must not be declared as private or final.@Bean methods are also discovered on base classes of a given component or configuration class, as well as on Java 8 default methods declared in interfaces implemented by the component or configuration class. This allows for a lot of flexibility in composing complex configuration arrangements, with even multiple inheritance being possible through Java 8 default methods as of Spring 4.2.Finally, a single class may hold multiple @Bean methods for the same bean, as an arrangement of multiple factory methods to use depending on available dependencies at runtime. This is the same algorithm as for choosing the “greediest” constructor or factory method in other configuration scenarios: The variant with the largest number of satisfiable dependencies is picked at construction time, analogous to how the container selects between multiple @Autowired constructors.
您可以将@Bean方法声明为static,允许在不创建包含它们的配置类作为实例的情况下调用它们。BeanFactoryPostProcessor 这在定义后处理器 bean(例如,类型or )时特别有意义BeanPostProcessor,因为这些 bean 在容器生命周期的早期就被初始化,并且应该避免在那个时候触发配置的其他部分。由于技术限制,对静态@Bean方法的调用永远不会被容器拦截,甚至在 @Configuration类中也不会(如本节前面所述):CGLIB 子类化只能覆盖非静态方法。因此,直接调用另一个@Bean方法具有标准的 Java 语义,从而导致直接从工厂方法本身返回一个独立的实例。方法的 Java 语言可见性@Bean不会立即影响 Spring 容器中生成的 bean 定义。您可以自由地声明您认为适合非@Configuration类的工厂方法,也可以在任何地方声明静态方法。但是,类中的常规@Bean方法@Configuration需要是可覆盖的——也就是说,它们不能被声明为privateor final@Bean方法也在给定组件或配置类的基类上发现,以及在组件或配置类实现的接口中声明的 Java 8 默认方法上发现。这为组合复杂的配置安排提供了很大的灵活性,甚至可以通过 Spring 4.2 的 Java 8 默认方法实现多重继承。最后,单个类可以@Bean为同一个 bean 保存多个方法,作为多个工厂方法的排列,根据运行时可用的依赖关系使用。这与在其他配置场景中选择“最贪婪”的构造函数或工厂方法的算法相同:在构造时选择具有最多可满足依赖项的变体,类似于容器如何在多个@Autowired构造函数之间进行选择。

1.10.6. Naming Autodetected Components

命名自动检测到的组件

When a component is autodetected as part of the scanning process, its bean name is generated by the BeanNameGenerator strategy known to that scanner. By default, any Spring stereotype annotation (@Component, @Repository, @Service, and @Controller) that contains a name value thereby provides that name to the corresponding bean definition.

当组件作为扫描过程的一部分被自动检测到时,其bean名称由该扫描仪已知的“BeanNameGenerator”策略生成。默认情况下,任何包含名称“value”的Spring原型注释(“@Component”、“Repository”、“Service”和“Controller”)都会将该名称提供给相应的bean定义。

If such an annotation contains no name value or for any other detected component (such as those discovered by custom filters), the default bean name generator returns the uncapitalized non-qualified class name. For example, if the following component classes were detected, the names would be myMovieLister and movieFinderImpl:

如果这样的注释不包含名称value或任何其他检测到的组件(例如由自定义过滤器发现的组件),则默认 bean 名称生成器将返回未大写的非限定类名称。例如,如果检测到以下组件类,则名称为myMovieListerand movieFinderImpl

@Service("myMovieLister")
public class SimpleMovieLister {// ...
}
@Repository
public class MovieFinderImpl implements MovieFinder {// ...
}

If you do not want to rely on the default bean-naming strategy, you can provide a custom bean-naming strategy. First, implement the BeanNameGenerator interface, and be sure to include a default no-arg constructor. Then, provide the fully qualified class name when configuring the scanner, as the following example annotation and bean definition show.

如果您不想依赖默认的 bean 命名策略,可以提供自定义 bean 命名策略。首先,实现 BeanNameGenerator 接口,并确保包含一个默认的无参数构造函数。然后,在配置扫描器时提供完全限定的类名,如以下示例注释和 bean 定义所示。

If you run into naming conflicts due to multiple autodetected components having the same non-qualified class name (i.e., classes with identical names but residing in different packages), you may need to configure a BeanNameGenerator that defaults to the fully qualified class name for the generated bean name. As of Spring Framework 5.2.3, the FullyQualifiedAnnotationBeanNameGenerator located in package org.springframework.context.annotation can be used for such purposes.
如果由于多个自动检测到的组件具有相同的非限定类名(即,具有相同名称但位于不同包中的类)而遇到命名冲突,您可能需要配置BeanNameGenerator默认为生成的完全限定类名的豆名。从 Spring Framework 5.2.3 开始, FullyQualifiedAnnotationBeanNameGenerator位于包中的包 org.springframework.context.annotation可用于此类目的。
@Configuration
@ComponentScan(basePackages = "org.example", nameGenerator = MyNameGenerator.class)
public class AppConfig {// ...
}
<beans><context:component-scan base-package="org.example"name-generator="org.example.MyNameGenerator" />
</beans>

As a general rule, consider specifying the name with the annotation whenever other components may be making explicit references to it. On the other hand, the auto-generated names are adequate whenever the container is responsible for wiring.

作为一般规则,只要其他组件可能显式引用它,请考虑使用注释指定名称。另一方面,只要容器负责接线,自动生成的名称就足够了。

1.10.7. Providing a Scope for Autodetected Components

为自动检测的组件提供范围

As with Spring-managed components in general, the default and most common scope for autodetected components is singleton. However, sometimes you need a different scope that can be specified by the @Scope annotation. You can provide the name of the scope within the annotation, as the following example shows:

与一般 Spring 管理的组件一样,自动检测组件的默认和最常见范围是singleton. 但是,有时您需要可以由@Scope注释指定的不同范围。您可以在注释中提供范围的名称,如以下示例所示:

@Scope("prototype")
@Repository
public class MovieFinderImpl implements MovieFinder {// ...
}
@Scope annotations are only introspected on the concrete bean class (for annotated components) or the factory method (for @Bean methods). In contrast to XML bean definitions, there is no notion of bean definition inheritance, and inheritance hierarchies at the class level are irrelevant for metadata purposes.
@Scope注释仅在具体 bean 类(用于注释组件)或工厂方法(用于@Bean方法)上进行自省。与 XML bean 定义相比,没有 bean 定义继承的概念,并且类级别的继承层次结构与元数据无关。

For details on web-specific scopes such as “request” or “session” in a Spring context, see Request, Session, Application, and WebSocket Scopes. As with the pre-built annotations for those scopes, you may also compose your own scoping annotations by using Spring’s meta-annotation approach: for example, a custom annotation meta-annotated with @Scope("prototype"), possibly also declaring a custom scoped-proxy mode.

有关 Web 特定范围的详细信息,例如 Spring 上下文中的“请求”或“会话”,请参阅请求、会话、应用程序和 WebSocket 范围。与这些范围的预构建注释一样,您也可以使用 Spring 的元注释方法来编写自己的范围注释:例如,使用 元注释的自定义注释@Scope("prototype"),也可能声明自定义范围代理模式。

To provide a custom strategy for scope resolution rather than relying on the annotation-based approach, you can implement the ScopeMetadataResolver interface. Be sure to include a default no-arg constructor. Then you can provide the fully qualified class name when configuring the scanner, as the following example of both an annotation and a bean definition shows:
要为范围解析提供自定义策略而不是依赖基于注释的方法,您可以实现该 ScopeMetadataResolver 接口。确保包含一个默认的无参数构造函数。然后,您可以在配置扫描器时提供完全限定的类名,如以下注释和 bean 定义示例所示:
@Configuration
@ComponentScan(basePackages = "org.example", scopeResolver = MyScopeResolver.class)
public class AppConfig {// ...
}
<beans><context:component-scan base-package="org.example" scope-resolver="org.example.MyScopeResolver"/>
</beans>

When using certain non-singleton scopes, it may be necessary to generate proxies for the scoped objects. The reasoning is described in Scoped Beans as Dependencies. For this purpose, a scoped-proxy attribute is available on the component-scan element. The three possible values are: no, interfaces, and targetClass. For example, the following configuration results in standard JDK dynamic proxies:

当使用某些非单例作用域时,可能需要为作用域对象生成代理。原因在Scoped Beans as Dependencies中进行了描述。为此,component-scan 元素上提供了 scoped-proxy 属性。三个可能的值是:nointerfacestargetClass。例如,以下配置会生成标准 JDK 动态代理:

@Configuration
@ComponentScan(basePackages = "org.example", scopedProxy = ScopedProxyMode.INTERFACES)
public class AppConfig {// ...
}
<beans><context:component-scan base-package="org.example" scoped-proxy="interfaces"/>
</beans>

1.10.8. Providing Qualifier Metadata with Annotations

提供带有注释的限定符元数据

The @Qualifier annotation is discussed in Fine-tuning Annotation-based Autowiring with Qualifiers. The examples in that section demonstrate the use of the @Qualifier annotation and custom qualifier annotations to provide fine-grained control when you resolve autowire candidates. Because those examples were based on XML bean definitions, the qualifier metadata was provided on the candidate bean definitions by using the qualifier or meta child elements of the bean element in the XML. When relying upon classpath scanning for auto-detection of components, you can provide the qualifier metadata with type-level annotations on the candidate class. The following three examples demonstrate this technique:

@Qualifier注释在Fine -tuning Annotation-based Autowiring with Qualifiers中讨论。该部分中的示例演示了使用@Qualifier注解和自定义限定符注解在解析自动装配候选时提供细粒度控制。因为这些示例基于 XML bean 定义,所以通过使用 XML 中元素的qualifierormeta 子元素在候选 bean 定义上提供限定符元数据bean。当依赖类路径扫描来自动检测组件时,您可以在候选类上为限定符元数据提供类型级别的注释。以下三个示例演示了这种技术:

@Component
@Qualifier("Action")
public class ActionMovieCatalog implements MovieCatalog {// ...
}
@Component
@Genre("Action")
public class ActionMovieCatalog implements MovieCatalog {// ...
}
@Component
@Offline
public class CachingMovieCatalog implements MovieCatalog {// ...
}
As with most annotation-based alternatives, keep in mind that the annotation metadata is bound to the class definition itself, while the use of XML allows for multiple beans of the same type to provide variations in their qualifier metadata, because that metadata is provided per-instance rather than per-class.
与大多数基于注解的替代方案一样,请记住注解元数据绑定到类定义本身,而 XML 的使用允许相同类型的多个 bean 提供其限定符元数据的变体,因为元数据是根据每个-实例而不是每个类。

1.10.9. Generating an Index of Candidate Components

生成候选组件的索引

While classpath scanning is very fast, it is possible to improve the startup performance of large applications by creating a static list of candidates at compilation time. In this mode, all modules that are targets of component scanning must use this mechanism.

虽然类路径扫描非常快,但可以通过在编译时创建静态候选列表来提高大型应用程序的启动性能。在这种模式下,作为组件扫描目标的所有模块都必须使用这种机制。

Your existing @ComponentScan or <context:component-scan/> directives must remain unchanged to request the context to scan candidates in certain packages. When the ApplicationContext detects such an index, it automatically uses it rather than scanning the classpath.
您现有的@ComponentScan<context:component-scan/>指令必须保持不变,才能请求上下文以扫描某些包中的候选人。当 ApplicationContext检测到这样的索引时,它会自动使用它而不是扫描类路径。

To generate the index, add an additional dependency to each module that contains components that are targets for component scan directives. The following example shows how to do so with Maven:

要生成索引,请向每个包含作为组件扫描指令目标的组件的模块添加一个附加依赖项。以下示例显示了如何使用 Maven 执行此操作:

<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context-indexer</artifactId><version>5.3.21</version><optional>true</optional></dependency>
</dependencies>

With Gradle 4.5 and earlier, the dependency should be declared in the compileOnly configuration, as shown in the following example:

对于 Gradle 4.5 及更早版本,应在compileOnly 配置中声明依赖项,如以下示例所示:

dependencies {compileOnly "org.springframework:spring-context-indexer:5.3.21"
}

With Gradle 4.6 and later, the dependency should be declared in the annotationProcessor configuration, as shown in the following example:

对于 Gradle 4.6 及更高版本,应在annotationProcessor 配置中声明依赖项,如下例所示:

dependencies {annotationProcessor "org.springframework:spring-context-indexer:5.3.21"
}

The spring-context-indexer artifact generates a META-INF/spring.components file that is included in the jar file.

spring-context-indexer工件会生成一个META-INF/spring.components包含在 jar 文件中的文件。

When working with this mode in your IDE, the spring-context-indexer must be registered as an annotation processor to make sure the index is up-to-date when candidate components are updated.
在 IDE 中使用此模式时,spring-context-indexer必须将其注册为注释处理器,以确保更新候选组件时索引是最新的。
The index is enabled automatically when a META-INF/spring.components file is found on the classpath. If an index is partially available for some libraries (or use cases) but could not be built for the whole application, you can fall back to a regular classpath arrangement (as though no index were present at all) by setting spring.index.ignore to true, either as a JVM system property or via the SpringProperties mechanism.
当在类路径中找到文件时,索引会自动启用META-INF/spring.components。如果索引对某些库(或用例)部分可用,但无法为整个应用程序构建,则可以通过设置spring.index.ignore为 回退到常规类路径安排(好像根本不存在索引) true,或者作为JVM 系统属性或通过 SpringProperties机制。

Spring参考文档翻译12--IOC容器10相关推荐

  1. Spring(二)IOC容器的初始化流程

    文章目录 一.Spring 核心容器类 1.1 BeanFactory 1.2 ApplicationContext 1.3 BeanDefinition 二.IOC容器的初始化 2.1 基于Xml的 ...

  2. spring之:XmlWebApplicationContext作为Spring Web应用的IoC容器,实例化和加载Bean的过程...

    它既是 DispatcherServlet 的 (WebApplicationContext)默认策略,又是 ContextLoaderListener 创建 root WebApplicationC ...

  3. Spring源码分析——IOC容器

    1.IOC容器的概念 理解IOC容器的概念之前首先需要了解依赖翻转(又称依赖倒置)的概念 许多复杂的应用都是通过多个类之间的彼此合作实现业务逻辑的,这使得每个对象都需要管理自己与其合作对象的依赖,而如 ...

  4. Spring参考文档翻译11--IOC容器09

    1.9. Annotation-based Container Configuration 基于注解的容器配置 Are annotations better than XML for configur ...

  5. Spring环境搭建,IoC容器初体验~

    由于最近的任务是关于IoC配置文件格式的转换,所以需要从Spring的IoC容器开始学起,今天根据网上的介绍搭建了Spring环境,并对其IoC容器进行了初体验.文章中涉及到的软件以及推荐的一本关于S ...

  6. JAVAWEB开发之Spring详解之——Spring的入门以及IOC容器装配Bean(xml和注解的方式)、Spring整合web开发、整合Junit4测试

    Spring框架学习路线 Spring的IOC Spring的AOP,AspectJ Spring的事务管理,三大框架的整合 Spring框架概述 什么是Spring?  Spring是分层的Java ...

  7. Spring揭秘1:IOC容器、bean的生命周期

    1 依赖注入 在IoC模式中,被注入对象又是通过哪些方式来通知IoC Service Provider为其提供适当服务的呢?----依赖注入方式 构造方法注入 setter方法注入 接口注入 1.1 ...

  8. 请解释下Spring 框架中的IOC 容器?

    Spring 中的org.springframework.beans 包和org.springframework.context 包构成了Spring 框架IOC 容器的基础. BeanFactory ...

  9. Spring源码:IOC容器

    Spring IOC 容器 最底层的IOC容器BeanFactory. 高级形态的IOC容器ApplicationContext. BeanFactory相关类图: ApplicationContex ...

  10. Spring是什么?IoC容器的理解

    1. Spring是什么? 我们通常所说的 Spring 指的是 Spring Framework(Spring 框架)⽤⼀句话概括 Spring:Spring 是包含了众多⼯具⽅法的 IoC 容器. ...

最新文章

  1. sqli-labs(10)
  2. 当深度学习遇上量化交易——因子挖掘篇
  3. qpython怎么用matplotlib_python-通过文本框的交互式matplotlib图
  4. 那些地方会用C语言多线程,如何用C语言实现多线程
  5. C# Http请求接口数据的两种方式Get and Post
  6. Spring Boot笔记-Hibernate中@ManyToOne及@OneToOne
  7. 数据:1inch昨日锁仓量达到7.7607亿美元
  8. vue 项目中常见的几个问题
  9. java2实用教程 (课后习题总结)
  10. 计算机辅助翻译 教学大纲,《计算机辅助翻译》本科课程教学大纲翻译本科
  11. [Python图像处理] 十七.图像锐化与边缘检测之Roberts算子、Prewitt算子、Sobel算子和Laplacian算子
  12. Java 使用谷歌翻译免费api,翻译文档
  13. 使用QT5+Opencv完成简单的图像处理及视频处理软件
  14. TCP通信协议基本操作
  15. 联想计算机系统重装,联想笔记本电脑重装系统教程
  16. 使用html2canvas 生成h5项目中需要的海报效果,uniapp 生成h5海报
  17. “数据闭环定义芯片”助力汽车智能化升级,辉羲智能亮相上海车展
  18. 什么是session
  19. html中让两段文字并列排放,言语理解:探究阅读之并列文段
  20. el-table 点击单元格可编辑 点击表头可修改 右击表头删除表头和内容

热门文章

  1. 多层石墨烯表皮电子皮肤【翻译】
  2. 仓库货位卡标识牌_仓库货位卡怎么使用?摆放、保存、使用原则都在这儿!
  3. 未来计算机的将朝着,未来计算机将朝着微型化、巨型化、网络化和 ( ) 方向发展。...
  4. Spring中bean的执行初始化和销毁方法的4种方式详解
  5. 傻瓜式学习webpack(四)——图片处理
  6. python提取图片中的信息
  7. 互联网+制造:自杀还是他杀?
  8. Android 5.0,6.0,7.0,8.0新特性整理
  9. linux php 安装图文教程下载,linux下php安装配置教程
  10. 【23考研】计算机择校信息库-福建高校计算机相关专业22专业目录分类汇总(按专业课分类汇总)