摘录一些Spring文档的内容(二)

基于注释的容器配置

通过基于注解的配置提供了XML设置的替代方法,该配置依赖于元数据(metadata)来连接组件。

注解

<context:annotation-config/>
只会在同一应用上下文寻找bean定义,所以,在WebApplicationContext中使用<context:annotation-config/>,它只会检查在Controller层标记@Autowired声明的bean而不会到你的Service层中去找(因此Controller和Service都要分别定义<context:annotation-config/>)
注意:<context:annotation-config/>和<context:component-scan>的区别

  • @Required
    被标注的bean必须的相关值必须被填充(注入), 如果没有被填充(注入),则容器会报错。这允许急切和明确的失败,以后避免NullPointerExceptions等
public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Required
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...

}

注意
如果你用java config形式配置bean的话@Required是不起作用的
https://stackoverflow.com/questions/16769360/how-does-required-annotation-work-with-javaconfig)

So, to summarize: @Required
doesn't work with @Configuration
classes by default. If you need to make sure that all your properties are set, you can just as well do it yourself when you create the bean in the @Bean
methods (By calling some init
method that performs such validations, or just supplying the required properties yourself). And if you really need to make the @Required
annotation work, you'd need to use your own implementation of the RequiredAnnotationBeanPostProcessor
, register it as a bean in the spring context and give up the benefits of context:annotation-config
.

  • @Autowired
    可以注解在setter方法上,构造器上,具有任意名称和/或多个参数的方法,字段上(fields),数组类型的字段或方法,集合类型的字段或方法上
public class MovieRecommender {

    @Autowired
    private MovieCatalog[] movieCatalogs;

    // ...

}

注意
Map类型需要key为String类型才能被注入,key值会对应bean名称。容器会将符合类型的bean都注入到map中,其中key值就是对应的bean名称。

  • @Primary
    @Autowired是根据类型自动装配的(@Resource(这个注解属于J2EE的),默认安装名称进行装配),按照类型的自动装配可能会导致多个候选,因此通常要对选择过程由更多的控制,其中一个方法时使用Spring的@Primary注解。当有多个附后要求的候选bean时,标有primary的Bean会被注入
public class MovieRecommender {

    @Autowired
    private ApplicationContext context;

    public MovieRecommender() {
    }

    // ...

}
@Configuration
public class MovieConfiguration {

    @Bean
    @Primary
    public MovieCatalog firstMovieCatalog() { ... }

    @Bean
    public MovieCatalog secondMovieCatalog() { ... }

    // ...

}
  • @Qualifier
    按照类型的自动装配可能会导致多个候选,因此通常要对选择过程由更多的控制,Spring的@Qualifier注释,可以将限定符值与特定参数关联,缩小类型匹配集
public class MovieRecommender {

    @Autowired
    @Qualifier("main")
    private MovieCatalog movieCatalog;

    // ...

}

@Qualifier也可以标注在单独的构造器参数或方法参数上。

public class MovieRecommender {

    private MovieCatalog movieCatalog;

    private CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public void prepare(@Qualifier("main")MovieCatalog movieCatalog,
            CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...

}
<?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
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

    <bean class="example.SimpleMovieCatalog">
        <qualifier value="main"/>

        <!-- inject any dependencies required by this bean -->
    </bean>

    <bean class="example.SimpleMovieCatalog">
        <qualifier value="action"/>

        <!-- inject any dependencies required by this bean -->
    </bean>

    <bean id="movieRecommender" class="example.MovieRecommender"/>

</beans>

限定符也适用于类型化的集合,如上所述,例如 Set<MovieCatalog>。在这种情况下,根据声明的限定符的所有匹配的bean将作为集合进行注入。这意味着限定词不一定是唯一的; 它们只是构成过滤标准。例如,您可以MovieCatalog使用相同的限定符值“action” 定义多个bean,所有这些bean都将注入到Set<MovieCatalog>注释中@Qualifier("action")。

注意
如果你打算按名称注入Bean,不要用@Autowired,请使用@Resource(JSR-250定义的)

  • @Resource
    @Resource默认按名称注入,如果没有明确指定名称,则默认名称来自字段名称或setter方法。在一个字段的情况下,它需要字段名称; 在setter方法的情况下,它将使用bean属性名称。如果没有明确指定名称,默认名称也找不到对应的bean就和@Autowired类似.
public class MovieRecommender {

    @Resource
    private CustomerPreferenceDao customerPreferenceDao;

    @Resource
    private ApplicationContext context;

    public MovieRecommender() {
    }

    // ...

}


以上几个注解,我都做了相应的练习去验证https://github.com/wingofthestar/SpringLearn

位于site.yourdiary.anno目录下


目录.png

@Controller、@Service、@Repository、@Component
@Component是标志着任何被Spring管理的组件(Bean)
@Repository, @Service, @Controller是对于@Component更具体的特定用例的组件。

你可以用 @Component注解组件类,但如果用@Repository,@Service或者@Controller ,你的类有可能能更好地被工具处理,或与切面进行关联。

  • 元注解
    Spring 提供的许多注解可以在你自己的代码中用作元注解。元注解是可以应用于另一个注解的注解。例如,@Service注解就是以@Component为元注解的
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component // Spring will see this and treat @Service in the same way as @Component
public @interface Service {

    // ....
}

元注解可以组合成组合注解,就比如在SpringMVC中@RestController就是由@Controller和@ResponseBody组合而成的。

  • 自动检测类和注册bean定义
    Spring可以自动检测注解有(stereotyped)的类,并在ApplicationContext中注册相应的BeanDeinitions.
    例如:
@Service
public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Autowired
    public SimpleMovieLister(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

}
@Repository
public class JpaMovieFinder implements MovieFinder {
    // implementation elided for clarity
}

为了自动检测这些类,并且注册相应的Bean,你需要添加在@Configuration类上标注@ComponentScan,并且标记basePackages属性为这两个类的父包。(也可以用逗号、分号、空格分隔的列出每个class的父包)。

java config写法

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

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
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="org.example"/>

</beans>

注意
<context:component-scan>启用(包含)了<context:annotation-config>的功能,所以使用了<context:component-scan>就不需要再添加<context:component-scan>

Furthermore, the AutowiredAnnotationBeanPostProcessor and CommonAnnotationBeanPostProcessor are both included implicitly 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.

AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor也同时被自动检测到并注册

使用过滤器自定义扫描(路径)

过滤器类型.png

下面的例子展示了configuration忽略了所有@Repository注解,并用"stub" respositories

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

使用JSR-330标准注解

从Spring 3.0开始,提供对JSR-330标准注释(依赖注入)的支持。这些注释以与Spring注释相同的方式进行扫描。你只需要在你的classpath中有相关的jar。

可以在maven的pom.xml中添加

<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>
  • 使用@Inject和@Named
    如果您想要使用限定名称作为应注入的依赖项,则应使用@Named注释
import javax.inject.Inject;
import javax.inject.Named;

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Inject
    public void setMovieFinder(@Named("main") MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...
}
  • @Named和@ManagedBean:@Component注释的标准等价物
    Instead of @Component, @javax.inject.Named or javax.annotation.ManagedBean may be used as follows:
import javax.inject.Inject;
import javax.inject.Named;

@Named("movieListener") // @ManagedBean("movieListener") could be used as well
public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Inject
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...
}

当使用@Named或@ManagedBean时可以使用与使用Spring注解完全相同的组件扫描

@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {
    ...
}
  • JSR-330标注注解的限制
Spring注解与JSR-330 标准注解的对比.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容