20191226 Spring官方文档(Core 1.10)

1.10。类路径扫描和托管组件

1.10.1。@Component和更多的构造型注释

@Repository批注是实现存储库(也被称为数据访问对象或DAO)角色或构造型的任何类的标记。该标记的用途是自动翻译 异常。

Spring提供进一步构造型注解:@Component@Service@Controller。@Component是任何Spring托管组件的通用构造型。 @Repository,@Service和@Controller是@Component针对更特定用例的专业化(分别在持久性,服务和表示层)。因此,您可以用@Component来注解你的组件类 ,但是,通过@Repository,@Service或者@Controller注解它们 ,你的类能更好地适合于通过工具处理,或与切面进行关联。例如,这些构造型注释更适合成为切入点的理想目标。@Repository,@Service和@Controller在Spring框架的将来版本中还可以包含其他语义。因此,如果您对于服务层选择使用@Component或@Service,@Service显然是更好的选择。同样,如前所述,@Repository在持久层中已经支持作为自动异常转换的标记。

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

@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;

}

然后,您无需声明proxyMode以下即可使用@SessionScope

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

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

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

1.10.3。自动检测类并注册Bean定义

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

@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {
    // ...
}

为简便起见,前面的示例可能使用了注释的value属性(即@ComponentScan("org.example"))。

<?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>

使用<context:component-scan>隐式启用<context:annotation-config>的功能 。<context:annotation-config>使用时通常不需要包含<context:component-scan>元素。

此外,当您使用component-scan元素时,AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor都隐式包括在内。这意味着将自动检测这两个组件并装配它们,而这一切都不需要XML中提供的任何bean配置元数据。

您可以禁用注册AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor,通过设置annotation-config属性值为false

1.10.4。使用过滤器自定义扫描

默认情况下,类注解有@Component,@Repository,@Service,@Controller, @Configuration,或自定义的自身带有@Component的注释,是唯一检测到的候选组件。但是,您可以通过应用自定义过滤器来修改和扩展此行为。将它们添加为@ComponentScanincludeFiltersexcludeFilters属性(或XML配置中<context:component-scan>元素的<context:include-filter /><context:exclude-filter />子元素)。每个过滤器元素都需要typeexpression属性。下表描述了过滤选项(type属性的值域):
过滤器类型 | 示例 | 描述
---|---|---
annotation (default) | org.example.SomeAnnotation | 在目标组件中的类型级别上存在或元存在的注释。
assignable | org.example.SomeClass | 目标组件可分配给(扩展或实现)的类(或接口)。
aspectj | org.example..Service+ | 目标组件要匹配的AspectJ类型表达式。
regex | org.example.Default.
| 要与目标组件的类名匹配的正则表达式。
custom | org.example.MyTypeFilter | org.springframework.core.type.TypeFilter接口的自定义实现。

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

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

您还可以通过设置注解的useDefaultFilters=false或通过提供标签的use-default-filters="false"的属性来禁用默认过滤器。这有效地禁用了对使用@Component@Repository@Service@Controller@RestController@Configuration进行注释或元注释的类的自动检测。

1.10.5。在组件中定义Bean元数据

@Component
public class FactoryMethodComponent {

    @Bean
    @Qualifier("public")
    public TestBean publicInstance() {
        return new TestBean("publicInstance");
    }

    public void doWork() {
        // Component method implementation omitted
    }
}

@Bean注释标识工厂方法和其它bean定义特性,如带一个限定值的@Qualifier注释。可以指定的其他方法级别的注解是 @Scope@Lazy和自定义限定器注解。

除了用于组件初始化的角色外,您还可以将@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);
    }
}

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

@Component
public class FactoryMethodComponent {

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

将@Bean在普通的Spring组件方法与Spring里的同行@Configuration类处理方式不同。不同之处在于,CGLIB并未增强@Component类来拦截方法和字段的调用。CGLIB代理是一种方法,通过该方法可以调用@Configuration类中的方法或@Bean方法中的字段来创建Bean元数据引用以协作对象。此类方法不是用普通的Java语义调用的,而是通过容器进行的,以提供通常的生命周期管理和Spring Bean的代理,即使通过程序调用@Bean方法引用其他Bean时也是如此。相反,在普通区域内调用@Component类中的@Bean方法或方法中的字段具有标准的Java语义,没有特殊的CGLIB处理或其他限制。

您可以将@Bean方法声明为static,从而允许在不将其包含的配置类创建为实例的情况下调用它们。在定义后处理器Bean(例如BeanFactoryPostProcessorBeanPostProcessor类型)时,这特别有意义,因为此类Bean在容器生命周期的早期进行了初始化,并且应避免在那时触发配置的其他部分。

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

@Bean方法的Java语言可见性不会对Spring容器中的结果bean定义产生直接影响。您可以随意声明自己的工厂方法,以适合非@Configuration类,也可以在任何地方使用静态方法。但是,@Configuration类中的常规@Bean方法必须是可重写的,也就是说,不得将其声明为privatefinal

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

最后,单个类可以为同一个bean 保留多个@Bean方法,这取决于在运行时可用的依赖项,以安排使用多个工厂方法。这与在其他配置方案中选择“最贪婪”的构造函数或工厂方法的算法相同:在构造时将选择具有最大可满足依赖关系数量的变体,类似于容器在多个@Autowired构造函数之间进行选择的方式。

1.10.6。命名自动检测的组件

当组件被自动检测为扫描过程的一部分时,其bean名称由扫描器已知的BeanNameGenerator策略生成。默认情况下,任何Spring构造型注解(@Component,@Repository,@Service和 @Controller),其中包含一个名称value,从而提供了相应的bean定义的名称。

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

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

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

@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>

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

1.10.7。为自动检测的组件提供作用域

@Scope("prototype")
@Repository
public class MovieFinderImpl implements MovieFinder {
    // ...
}

@Scope注释仅在具体的bean类(对于带注释的组件)或工厂方法(对于@Bean方法)上进行内省。 与XML bean定义相反,没有bean定义继承的概念,并且在类级别的继承层次结构与元数据目的无关。

要提供用于范围解析的自定义策略,而不是依赖于基于注释的方法,可以实现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>

使用某些非单作用域时,可能有必要为作用域对象生成代理。为此,在component-scan元素上可以使用scoped-proxy属性。三个可能的值是:nointerfaces,和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。提供带有注释的限定符元数据

参考

@Component
@Qualifier("Action")
public class ActionMovieCatalog implements MovieCatalog {
    // ...
}
@Component
@Genre("Action")
public class ActionMovieCatalog implements MovieCatalog {
    // ...
}
@Component
@Offline
public class CachingMovieCatalog implements MovieCatalog {
    // ...
}

与大多数基于注释的替代方法一样,请记住,注释元数据绑定到类定义本身,而XML的使用允许相同类型的多个bean提供其限定符元数据的变体,因为该元数据是按instance而不是按类。

1.10.9。生成候选组件的索引

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

您现有的@ComponentScan<context:component-scan>指令必须保持原样,以请求上下文扫描某些软件包中的候选对象。当 ApplicationContext检测到这样的索引时,它将自动使用它而不是扫描类路径。

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

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

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

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

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

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

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

在IDE中使用此模式时,必须将spring-context-indexer注册为注释处理器,以确保在更新候选组件时索引是最新的。

在类路径上找到 META-INF/spring.components 时,索引将自动启用。如果某个索引对于某些库(或用例)部分可用,但无法为整个应用程序构建,您可以通过将spring.index.ignore设置为true来回退到常规的类路径安排(好像根本没有索引),可以将其设置为系统属性,也可以将其设置为类路径根目录下的spring.properties文件。

原文地址:https://www.cnblogs.com/huangwenjie/p/12104016.html

时间: 2024-10-11 04:12:32

20191226 Spring官方文档(Core 1.10)的相关文章

20200106 Spring官方文档【归档】

目录 启动 Overview Core IoC容器 1.1.Spring IoC容器和Bean简介 1.2.容器概述 1.3.Bean总览 1.4.依赖关系 1.5.Bean Scopes 1.6.自定义Bean的性质 1.7.Bean定义继承 1.8.容器扩展点 1.9.基于注释的容器配置 1.10.类路径扫描和托管组件 1.11.使用JSR 330标准注释 1.12.基于Java的容器配置 1.13.Environment 抽象 1.14.注册一个LoadTimeWeaver 2. Reso

Spring 总览及 IOC 容器的使用 —— Spring 官方文档解读(一)

Spring 总览及 IOC 容器的使用 -- Spring 官方文档解读(一) 什么是 Spring? spring 这个词在不同情况下有不同意义.可以指 Spring 框架本身,但更多地被用来表示 Spring 整个家族的产品. 设计理念 学习框架必须要知道它的设计理念,Spring 框架有着以下的理念: Spring 让你在架构种的各个层面有更多的选择,并且允许你尽晚的做出决策.比如,你在项目完成后可以通过更改配置来切换持久层的提供者. Spring 具有强大的灵活性,它不在意你是如何完成

20200103 Spring官方文档(Core 3)

3.验证,数据绑定和类型转换 考虑将验证作为业务逻辑是有利有弊,Spring提供了一种验证(和数据绑定)设计,但并不排除其中任何一个. 具体来说,验证不应与Web层绑定,并且应该易于本地化,并且应该可以插入任何可用的验证器. 考虑到这些问题,Spring提出了一个Validator接口,该接口既基本又可以在应用程序的每一层中使用. 数据绑定对于使用户输入动态绑定到应用程序的域模型(或用于处理用户输入的任何对象)非常有用. Spring提供了恰当地命名为DataBinder的功能. Validat

20200105 Spring官方文档(Core 4)

4.Spring表达式语言(SpEL) Spring表达式语言(简称 SpEL)是一种功能强大的表达式语言,支持在运行时查询和操作对象图.语言语法与Unified EL相似,但提供了其他功能,最著名的是方法调用和基本的字符串模板功能. Spring Expression Language的创建是为了向Spring社区提供一种受良好支持的表达式语言,该语言可用于该版本中的所有产品.它并不直接与Spring绑定,可以独立使用. 4.1.评价(Evaluation) 以下代码介绍了SpEL API来评

20191224 Spring官方文档(Core 1.1-1.4)

1. IoC容器 1.1.Spring IoC容器和Bean简介 org.springframework.beans和org.springframework.context包是Spring框架的IoC容器的基础.BeanFactory 接口提供了一种高级配置机制,能够管理任何类型的对象. ApplicationContext是BeanFactory的子接口.它增加了: 与Spring的AOP功能轻松集成 消息资源处理(用于国际化) 活动发布 应用层特定的上下文,例如用于Web应用程序中的WebA

20191225 Spring官方文档(Core 1.5)

1.5.Bean Scopes 创建bean定义时,将创建一个配方,用于创建该bean定义所定义的类的实际实例.Bean定义是配方的想法很重要,因为它意味着与类一样,您可以从一个配方中创建许多对象实例. Spring Framework支持六个作用域,四个仅在Web环境的Spring ApplicationContext中可用.您还可以创建自定义作用域. 范围 描述 singleton (默认)将每个Spring IoC容器的单个bean定义范围限定为单个对象实例. prototype 将单个b

20191225 Spring官方文档(Core 1.6-1.8)

1.6.自定义Bean的性质 Spring框架提供了许多接口,可用于自定义Bean的性质. 1.6.1.生命周期回调 为了与容器对bean生命周期的管理进行交互,可以实现Spring的 InitializingBean和DisposableBean接口.容器调用afterPropertiesSet()和destroy()使bean在初始化和销毁bean时执行某些操作. 通常,JSR-250 @PostConstruct和@PreDestroy注释被认为是在现代Spring应用程序中接收生命周期回

spring 官方文档

英文 http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/ 翻译(1-6章) http://blog.csdn.net/tangtong1/article/details/51326887 翻译(7章) http://blog.csdn.net/tangtong1/article/details/51960382 翻译(1-6)

Spring官方文档——日志

2.3.2 日志 日志对于Spring来说非常重要(废话,日志对哪个系统不重要?),因为 a)它是唯一强制的外部依赖,b)每个人都希望在使用某个工具时可以看到一些友好地输出,c)Spring集成了很多其他的工具,它们也都有自己的日志依赖.应用开发者的一个目标通常是:对于整个应用来说(包括所有的外部组件),集中创建一个统一的日志配置.由于现在有如此多的日志框架,这个选择看起来会变得更难. Logging is a very important dependency for Spring becau