1.10. Classpath Scanning and Managed Components

上一节 1.9. Annotation-based Container Configuration

目录

下一节 1.11. Using JSR 330 Standard Annotations

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指定在Spring容器中生成每个BeanDefinition的
配置元数据。
上一节(基于注释的容器配置)演示了如何通过源代码级注释提供大量配置元数据。
然而,即使在这些示例中,“基本”bean definitions也显式地定义在XML文件中,
而注释仅驱动依赖项注入。
本节描述通过扫描类路径隐式检测候选组件的k可选方案。
候选组件是与筛选标准匹配的类,并有相应的bean definition 注册到容器中。
这样就不需要使用XML来执行bean注册。
相反,您可以使用注释(例如@Component)、AspectJ类型表达式或您自己的
自定义筛选标准来选择哪些类已经向容器注册了bean definitions。

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核心框架的一部分。
这允许您使用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](https://github.com/spring-projects/spring-framework/wiki/Spring-Annotation-Programming-Model) 章节中所述。(https://docs.spring.io/spring/docs/5.2.7.RELEASE/spring-framework-reference/data-access.html#orm-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
1.10.2. 使用元注释和组合注释

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  // @1
public @interface Service {

    // ...
}

@1 The Component causes @Service to be treated in the same way as @Component.

@Service 被 Component 以 @Component相同的方式处理。

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

您还可以组合元注释来创建“组合注释”。
例如,Spring MVC的@RestController注释由
@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.(https://github.com/spring-projects/spring-framework/wiki/Spring-Annotation-Programming-Model)

有关更多细节,请参见S Spring Annotation Programming Model  wiki页面。

1.10.3. Automatically Detecting Classes and Registering Bean Definitions
1.10.3. 自动检测类并注册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可以自动检测原型类,并向ApplicationContext注册相应的BeanDefinition实例。
例如,以下两个类符合这种自动检测:

@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/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://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:component-scan> 的时候 不需要包含<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 https://stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources).

类路径包的扫描要求类路径中存在相应的目录项。
当您使用Ant构建JAR时,请确保没有激活JAR任务的文件切换。
另外,在某些环境中,基于安全策略可能不会公开类路径目录
—例如,JDK 1.7.0_45或更高版本上的独立应用程序
(需要在清单中设置“Trusted-Library”
—请参见https://stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources)。

On 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).

在JDK 9的模块路径(Jigsaw)上,Spring的类路径扫描通常按预期工作。
但是,请确保在模块信息描述符中导出组件类。
如果希望Spring调用类的非公共成员,请确保它们是“打开的”
(也就是说,它们在模块信息描述符中使用open声明而不是export声明)。

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 元素时,AutowiredAnnotationBeanPostProcessor
和CommonAnnotationBeanPostProcessor都是隐式包含的。
这意味着这两个组件是自动检测并连接在一起的
——所有这些都不需要XML提供任何bean配置元数据。

You can disable the registration of AutowiredAnnotationBeanPostProcessor and CommonAnnotationBeanPostProcessor by including the annotation-config attribute with a value of false.

你可以禁用AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor的注册,
方法是将 annotation-config 属性的值设为false。

1.10.4. Using Filters to Customize Scanning
1.10.4. 使用过滤器自定义扫描

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 /> 的子元素 )。
每个筛选器元素都需要类型和表达式属性。下表描述了筛选选项:

Table 5. Filter Types
Filter TypeExample ExpressionDescription
annotation (default)org.example.SomeAnnotationAn annotation to be present or meta-present at the type level in target components.
assignableorg.example.SomeClassA class (or interface) that the target components are assignable to (extend or implement).
aspectjorg.example…* Service+An AspectJ type expression to be matched by the target components.
regexorg.example.Default.*A regex expression to be matched by the target components’ class names.
customorg.example.MyTypeFilterA custom implementation of the org.springframework.core.type.TypeFilter interface.
Filter TypeExample ExpressionDescription
annotation (default)org.example.SomeAnnotation在目标组件的类型级别上呈现或元呈现的注释.
assignableorg.example.SomeClass目标组件可分配给(扩展或实现)的类(或接口).
aspectjorg.example…* Service+目标组件匹配的AspectJ类型表达式.
regexorg.example.Default.*与目标组件的类名匹配的正则表达式.
customorg.example.MyTypeFilterorg.springframework.core.type.TypeFilter 的自定义实现接口.

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

下面的示例显示了忽略所有@Repository注释但使用 stub 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 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
1.10.5. 在组件中定义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 definition元数据。
您可以使用与在@Configuration注释类中定义bean元数据相同的
@Bean注释来做到这一点。下面的例子展示了如何做到这一点:

@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 definition,其中有一个引用方法
publicInstance()的工厂方法。
@Bean注释标识工厂方法和其他bean definition 属性,
例如通过@Qualifier注释标识的限定符值。
其他可以指定到方法级别注释是@Scope、@Lazy和自定义的qualifier 注释。

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.
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:

除了作为组件初始化的角色之外,你还可以将@Lazy注释放在用
@Autowired或@Inject标记的注入点上。
在这个情况下,它导致注入一个延迟解析代理。
如前所述,支持自动生成的字段和方法,另外还支持@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
    @Bean
    protected 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;
    }

    @Bean
    private TestBean privateInstance() {
        return new TestBean("privateInstance", i++);
    }

    @Bean
    @RequestScope
    public 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 #{ }. For @Value annotations, an expression resolver is preconfigured to look for bean names when resolving expression text.

该示例将字符串方法参数country自动转换为另一个名为privateInstance的
bean上的age属性的值。
一个Spring Expression语言元素通过符号#{ <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实例的实际创建,不适用于现有实例的注入。
因此,这个特性对 prototype 类型的bean最有意义。
对于其他作用于类型的bean,工厂方法只能看到在给定范围内触发
新bean实例创建的注入点(例如,触发lazy singleton 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组件中的@Bean方法与Spring @Configuration类中的
对应方法处理方式不同。
区别在于@Component类没有通过CGLIB增强来拦截方法和字段的调用。
CGLIB代理是通过调用@Configuration类中@Bean方法中的方法或字段来
创建对协作对象的bean元数据引用的方法。
这些方法不是用普通的Java语义调用的,而是通过容器来提供通常的
生命周期管理和Spring bean的代理,甚至在通过编程调用@Bean
方法引用其他bean时也是如此。
相反,在普通的@Component类中调用@Bean方法或字段具有标准的
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.

您可以将@Bean方法声明为静态的,允许在不将其包含的配置类
创建为实例的情况下调用它们。
这在定义 post-processor bean
(例如BeanFactoryPostProcessor或BeanPostProcessor类型)
时特别有意义,因为这样的bean在容器生命周期的早期被初始化,
应该避免在此时触发配置的其他部分。

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.

容器永远不会拦截对静态@Bean方法的调用,甚至在@Configuration类中也不会
(如本节前面所述),由于技术限制:CGLIB子类化只能覆盖非静态方法。
因此,对另一个@Bean方法的直接调用具有标准的Java语义,
从而直接从工厂方法本身返回一个独立的实例。

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.

Java语言中@Bean方法的可见性对Spring容器中生成的bean definition没有直接影响。
您可以自由地在 非@Configuration类中声明您的工厂方法,
也可以在任何地方声明静态方法。
但是,@Configuration类中的常规@Bean方法需要被重写
——也就是说,它们不能被声明为private或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.

@Bean方法也可以在给定component 或 configuration类的基类中发现,
也可以在Java 8中在 component 或 configuration 类实现的接口中声明的
默认方法中声明。
这为组合复杂配置安排提供了很大的灵活性,甚至可以通过Spring 4.2中的
Java 8默认方法实现多重继承。

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保留多个@Bean方法,作为多个工厂方法的安排,
在运行时根据可用的依赖项使用。
这与在其他配置场景中选择“贪婪的”构造函数或工厂方法是相同的算法:
在构建时选择可满足依赖关系最多的变量,类似于容器在多个@Autowired
构造函数之间进行选择。

1.10.6. Naming Autodetected Components
1.10.6. 命名自动检测组件

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 策略生成。
默认情况下,任何包含名称值的Spring原型注释
(@Component, @Repository, @Service,和@Controller)
将该名称提供给相应的bean definition。

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:

如果这样的注释不包含任何名称值,或者不包含任何其他检测到的组件
(比如那些由自定义过滤器发现的组件),
那么默认的bean名称生成器将返回小写且非限定类名。
例如,如果检测到以下组件类,名称将是myMovieLister和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,它默认为生成的bean名的完全限定类名。
在Spring Framework 5.2.3中,FullyQualifiedAnnotationBeanNameGenerator 
(位于package 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
1.10.7. 为自动检测组件设置作用域

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 definitions相反,不存在bean definitions继承的概念,
而且类级别的继承层次结构与元数据目的无关。

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上下文中的“request”或“session”,
请参阅章节 - Request, Session, Application, and WebSocket Scopes。
与为这些作用域预构建的注释一样,您也可以通过使用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:

在使用某些非 singleton 作用域时,可能需要为作用域对象生成代理。
其原因在作用域bean中描述为依赖关系。
为此,component-scan元素上有一个 scoped-proxy 属性。
三个可能的值是:no、interface和targetClass。
例如,以下配置导致了标准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
1.10.8.提供带有注释的限定符元数据

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注释和自定义的 qualifier注释的使用,
以在解析自动装配候选时提供细粒度的控制。
因为那些示例基于XML bean definitions,所以qualifier元数据是通过
使用XML中bean元素的限定符或元子元素在候选bean definitions 上提供的。
当依赖类路径扫描来自动检测组件时,您可以在候选类上提供带有类型级别
注释的qualifier元数据。
下面的三个例子演示了这种技术:

@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
1.10.9. 为候选组件生成索引

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 target of component scan must use this mechanism.

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

Your existing @ComponentScan or <context:component-scan directives must stay as is 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.2.7.RELEASE</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.2.7.RELEASE"
}

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:{spring-version}"
}

That process generates a META-INF/spring.components file that is included in the jar file.

该过程生成包含在jar文件中的META-INF/spring.components文件。

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上下文索引器注册为注释处理器,
以确保在更新候选组件时index是最新的。

The index is enabled automatically when a META-INF/spring.components 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 fallback to a regular classpath arrangement (as though no index was present at all) by setting spring.index.ignore to true, either as a system property or in a spring.properties file at the root of the classpath.

当在类路径中找到META-INF/spring.components时,索引会自动启用。
如果索引对于某些库(或用例)是部分可用的,但不能为整个应用程序构建,
那么您可以通过设置spring.index.ignore=true 回到常规的类路径安排
(就像根本没有索引一样)。
无论是作为系统属性还是在 spring.properties 文件位于类路径的根。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值