Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->使用spring framework的IoC容器功能----->方法二:使用annotion配置beans之间的依赖关系

annotation-based configurations

1.概述:

    • spring framework支持三种形式的configuration,xml-based configuration、annotion-based configuration、Java-based configuration。这三种方法各有优缺点,开发者可以根据实际需要选取某种方式编写配置代码来配置beans之间的依赖关系,也可以混合使用多种方式来编写配置代码。
    • spring framework除了拥有自己定义的annotion之外,还支持其他标准所定义的annotion,如
        • Spring 2.5 also added support for JSR-250 annotations such as @PostConstruct, and @PreDestroy.
        • Spring 3.0 added support for JSR-330 (Dependency Injection for Java) annotations contained in the javax.inject package such as @Inject and @Named
    • 如果程序中同时使用了annotion-based configuration和xml-based configuration,那么xml中的配置信息会覆盖annotion中的配置信息。

2.spring framework所支持的注释

    • spring framework自定义的annotion:
        • @Required,指示某个属性必须被赋初始值,若没被赋初始值则抛出异常
          • 该注解可以放在setter()或者init method上,使得实例化相应bean时,对应的属性必须被赋初始值
          • example,
          • public class SimpleMovieLister {
            
                private MovieFinder movieFinder;
            
                @Required
                public void setMovieFinder(MovieFinder movieFinder) {
                    this.movieFinder = movieFinder;
                }
            
                // ...
            
            }
              
        • @Autowired自动初始化,给参数或者属性赋初始值
          • 该注解可以放置在某个构造函数上或者被放置在setter函数上,也可以被放置在某个含参数的成员函数上,也可以直接修饰一个属性
          • @Autowired是根据type匹配,并注册dependencies,有时候按照type匹配会匹配上多个bean实例,这时就需要@Autowired和@Primary、@Qulifier注解搭配使用
          • @Autowired方式和@Resource注解都可以配置beans之间的依赖关系,前者按照type进行匹配,后者按照name进行匹配,通常我们建议使用@Resource注解配置依赖关系
          • public class MovieRecommender {
            
                private final CustomerPreferenceDao customerPreferenceDao;
            
                @Autowired
                public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
                    this.customerPreferenceDao = customerPreferenceDao;
                }
            
                // ...
            
            }
          • public class SimpleMovieLister {
            
                private MovieFinder movieFinder;
            
                @Autowired
                public void setMovieFinder(MovieFinder movieFinder) {
                    this.movieFinder = movieFinder;
                }
            
                // ...
            
            }
            public class MovieRecommender {
            
                private MovieCatalog movieCatalog;
            
                private CustomerPreferenceDao customerPreferenceDao;
            
                @Autowired
                public void prepare(MovieCatalog movieCatalog,
                        CustomerPreferenceDao customerPreferenceDao) {
                    this.movieCatalog = movieCatalog;
                    this.customerPreferenceDao = customerPreferenceDao;
                }
            
                // ...
            
            }

            You can apply @Autowired to fields as well and even mix it with constructors:

            public class MovieRecommender {
            
                private final CustomerPreferenceDao customerPreferenceDao;
            
                @Autowired
                private MovieCatalog movieCatalog;
            
                @Autowired
                public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
                    this.customerPreferenceDao = customerPreferenceDao;
                }
            
                // ...
            
            }
            public class MovieRecommender {
            
                @Autowired
                private MovieCatalog[] movieCatalogs;
            
                // ...
            
            }
            public class MovieRecommender {
            
                private Set<MovieCatalog> movieCatalogs;
            
                @Autowired
                public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
                    this.movieCatalogs = movieCatalogs;
                }
            
                // ...
            
            }
          • public class MovieRecommender {
            
                private Map<String, MovieCatalog> movieCatalogs;
            
                @Autowired
                public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
                    this.movieCatalogs = movieCatalogs;
                }
            
                // ...
            
            }
            public class SimpleMovieLister {
            
                private MovieFinder movieFinder;
            
                @Autowired(required=false)
                public void setMovieFinder(MovieFinder movieFinder) {
                    this.movieFinder = movieFinder;
                }
            
                // ...
            
            }
              
        • @Order or standard @Priority annotation

          • Your beans can implement the org.springframework.core.Ordered interface or either use the @Order or standard @Priority annotation if you want items in the array or list to be sorted into a specific order.  

              
        • @Primary

          • 使用该注解微调@autowired注解,@Autowired注解默认情况下会使IOC容器按照type类型注入dependencies,但是按照type进行匹配的话有可能会有多个候选方案都满足匹配条件,这会抛出异常,所以使用@Primary对@Autowired进行更精确的控制,使得有多个bean实例都满足要求时,只选用使用@Primary 标注的实例被用于注册到其他的bean实例中

          • @Configuration
            public class MovieConfiguration {
            
                @Bean
                @Primary
                public MovieCatalog firstMovieCatalog() { ... }
            
                @Bean
                public MovieCatalog secondMovieCatalog() { ... }
            
                // ...
            
            }

            With such configuration, the following MovieRecommender will be autowired with the firstMovieCatalog.

            public class MovieRecommender {
            
                @Autowired
                private MovieCatalog movieCatalog;
            
                // ...
            
            }

            上述配置和下面的xml-based configuration等效:

            <?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" primary="true">
                    <!-- inject any dependencies required by this bean -->
                </bean>
            
                <bean class="example.SimpleMovieCatalog">
                    <!-- inject any dependencies required by this bean -->
                </bean>
            
                <bean id="movieRecommender" class="example.MovieRecommender"/>
            
            </beans>
        •  @Qualifier
          • 和@Primary注解一样,这个注解也是用于有多个bean实例符合备选条件的情况,当有多个bean实例符合备选条件时,IOC容器会不知道应该选择哪个实例作为依赖注入其他bean实例,这时就需要使用@Qulifier注解来告诉IOC容器应该选择哪个具体的bean实例作为被注入的bean实例
          • public class MovieRecommender {
            
                @Autowired
                @Qualifier("main")
                private MovieCatalog movieCatalog;
            
                // ...
            
            }

            The @Qualifier annotation can also be specified on individual constructor arguments or method parameters:

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

            

3.如何使用spring framework中的annotion-based configuration

    • step1,首先弄懂spring framework中支持哪些注解,如@required、@autowired。。。
    • step2,在spring 的IOC容器中声明相应的bean,以使得IOC容器可以识别这些annotion
      • 概述,可以有三种方法声明annotion相关的bean,从而使得IOC容器可以识别这些annotion
      • 方法一,直接声明相应注解对应的bean,如若要使用 @Required注解,就必须声明RequiredAnnotationBeanPostProcessor的Bean
          • AutowiredAnnotationBeanPostProcessor,@Autowired
          • CommonAnnotationBeanPostProcessor,@Resource、@PostConstruct、@PreDestroy
          • PersistenceAnnotationBeanPostProcessor,@PersistenceContext
          • RequiredAnnotationBeanPostProcessor,@Required
          • 。。。    
      • 方法二,直接通过<context:annotation-config/>来将上述所有注解相关的XxxAnnotionBeanPostProcessor都包含进对应的IOC容器,使得该容器可以识别所有的注解
      • 方法三,可以直接通过<context:component-scan base-package="pack.pack"/>使得IOC容器可以识别上述所有注解
      • 更多 解释参见博客:如何使得spring framework相关的注解annotion生效
      • 具体操作:spring-configuration.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">
         
            <!--在spring的配置文件(即spring的IOC容器)中添加以下配置信息,使得spring IOC容器可以识别spring framework中各个注解是什么意思
        下面的一行代码实际上为该IOC容器引入了AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor, PersistenceAnnotationBeanPostProcessor, 以及 the aforementioned RequiredAnnotationBeanPostProcessor,这样一来该IOC容器就可以识别@Autowired、(@Resource、@PostConstruct、@PreDestroy)、@PersistenceContext、@Required等注解了-->
            <context:annotation-config/>
        
        </beans>
    • step3,明确上述代码虽然配置IOC容器使得该IOC容器能够识别相关注解,但是这个识别是有一定范围的:即该配置使得该IOC容器只会扫描该容器范围之内的bean的annotion信息,范围之外的annotion信息它是不会理会的。



          

  

学习的过程中总会得到一些心得体会,认真地将它们记录下来并分享给每一个愿意花费时间去阅读它们的人,然后意外地收获某个读者的评论,从而激发出新的感想,是一件十分令人欢快的事。如果你也在研习这方面的知识,欢迎加入到我们的队伍中来,和我们一起进步吧(^_^)
原文地址:https://www.cnblogs.com/lxrm/p/6278312.html