zoukankan      html  css  js  c++  java
  • 【Java】Spring之基于注释的容器配置(四)

    注释是否比配置Spring的XML更好?

      基于注释的配置的引入引发了这种方法是否比XML“更好”的问题。答案是每种方法都有其优点和缺点,通常,由开发人员决定哪种策略更适合他们。由于它们的定义方式,注释在其声明中提供了大量上下文,从而导致更短更简洁的配置。但是,XML擅长在不触及源代码或重新编译它们的情况下连接组件。一些开发人员更喜欢将布线靠近源,而另一些开发人员则认为注释类不再是POJO,而且配置变得分散且难以控制。

      无论选择如何,Spring都可以兼顾两种风格,甚至可以将它们混合在一起。

      注意:

    1 注释注入在XML注入之前执行。因此,XML配置会覆盖通过这两种方法连接的属性的注释。

    Spring开启注释

      1、<context:annotation-config> :是用于激活那些已经在spring容器里注册过的bean(无论是通过xml的方式还是通过package sanning的方式)上面的注解。

      2、<context:component-scan>:除了具有<context:annotation-config>的功能之外,<context:component-scan>还可以在指定的package下扫描以及注册javabean 。

    Spring常用注释

      @Required

      @Required注释适用于bean属性setter方法,此批注指示必须在配置时通过bean定义中的显式属性值或通过自动装配填充受影响的bean属性。如果尚未填充受影响的bean属性,则容器将引发异常。

     1 public class SimpleMovieLister {
     2 
     3     private MovieFinder movieFinder;
     4 
     5     @Required
     6     public void setMovieFinder(MovieFinder movieFinder) {
     7         this.movieFinder = movieFinder;
     8     }
     9 
    10     // ...
    11 }

      @Autowired

      可以将@Autowired注释应用于构造函数,还可以将@Autowired注释应用于“传统”setter方法,还可以将注释应用于具有任意名称和多个参数的方法

     1 public class MovieRecommender {
     2 
     3     private final CustomerPreferenceDao customerPreferenceDao;
     4 
     5     @Autowired
     6     private MovieCatalog movieCatalog;
     7 
     8     @Autowired
     9     public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
    10         this.customerPreferenceDao = customerPreferenceDao;
    11     }
    12 
    13     @Autowired(required = false)
    14     public void setMovieFinder(MovieCatalog movieCatalog) {
    15         this.movieCatalog = movieCatalog;
    16     }
    17 
    18     // ...
    19 }

      @Primary

      由于按类型自动装配可能会导致多个候选人,因此通常需要对选择过程进行更多控制。实现这一目标的一种方法是使用Spring的@Primary注释。@Primary表示当多个bean可以自动装配到单值依赖项时,应该优先选择特定的bean。如果候选者中只存在一个主bean,则它将成为自动装配的值。

     1 @Configuration
     2 public class MovieConfiguration {
     3 
     4     @Bean
     5     @Primary
     6     public MovieCatalog firstMovieCatalog() { ... }
     7 
     8     @Bean
     9     public MovieCatalog secondMovieCatalog() { ... }
    10 
    11     // ...
    12 }

      @Resource

      @Resource采用名称属性。默认情况下,Spring将该值解释为要注入的bean名称。换句话说,它遵循按名称语义,如以下示例所示:

      如果未明确指定名称,则默认名称是从字段名称或setter方法派生的。如果是字段,则采用字段名称。在setter方法的情况下,它采用bean属性名称

    1 public class SimpleMovieLister {
    2 
    3     private MovieFinder movieFinder;
    4 
    5     @Resource(name="myMovieFinder") 
    6     public void setMovieFinder(MovieFinder movieFinder) {
    7         this.movieFinder = movieFinder;
    8     }
    9 }

      @PostConstruct 和 @PreDestroy

      一个bean进行初始化时,回调@PostConstruct注释的方法

      一个bean进行销毁时,回调@PreDestroy注释的方法

     1 public class CachingMovieLister {
     2 
     3     @PostConstruct
     4     public void populateMovieCache() {
     5         // populates the movie cache upon initialization...
     6     }
     7 
     8     @PreDestroy
     9     public void clearMovieCache() {
    10         // clears the movie cache upon destruction...
    11     }
    12 }

      @Component

      表示一个带注释的类是一个“组件”,成为Spring管理的Bean。当使用基于注解的配置和类路径扫描时,这些类被视为自动检测的候选对象。同时  

      @Component是任何Spring管理组件的通用构造型。@Repository,@Service和,@Controller是@Component更具体的用例的专业化(分别在持久性,服务和表示层)。因此,您可以来注解你的组件类有 @Component,但是,通过与注解它们@Repository,@Service或者@Controller ,你的类能更好地被工具处理,或与切面进行关联。

     1 package com.test.spring.beanannotation;
     2 
     3 import org.springframework.context.annotation.Scope;
     4 import org.springframework.stereotype.Component;
     5 
     6 // @Component("beanAnno")
     7 @Component
     8 // @Scope("prototype")
     9 @Scope
    10 public class BeanAnnotation {
    11     
    12     public void say(String arg) {
    13         System.out.println("BeanAnnotation:" + arg);
    14     } 
    15      
    16     public void myHashCode() {
    17         System.out.println("BeanAnnotation:" + this.hashCode());
    18     }
    19  
    20 }

      @Component还是一个元注解。

    1 @Target(ElementType.TYPE)
    2 @Retention(RetentionPolicy.RUNTIME)
    3 @Documented
    4 @Component 
    5 public @interface Service {
    6 
    7     // ....
    8 }

      @Configuration

      声明当前类是一个配置类(相当于一个Spring配置的xml文件)

      @ComponentScan

      自动扫描指定包

    1 @Configuration
    2 @ComponentScan(basePackages = "org.example")
    3 public class AppConfig  {
    4     ...
    5 }

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

      替代方法使用XML:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xsi:schemaLocation="http://www.springframework.org/schema/beans
     6         https://www.springframework.org/schema/beans/spring-beans.xsd
     7         http://www.springframework.org/schema/context
     8         https://www.springframework.org/schema/context/spring-context.xsd">
     9 
    10     <context:component-scan base-package="org.example"/>
    11 
    12 </beans>

      @Bean 和 @Configuration

      Spring的新Java配置支持中的中心工件是 @Configuration注释类和@Bean注释方法。

      该@Bean注释被用于指示一个方法实例,配置和初始化为通过Spring IoC容器进行管理的新对象。对于那些熟悉Spring的<beans/>XML配置的人来说,@Bean注释与<bean/>元素扮演的角色相同。你可以@Bean在任何Spring中使用-annotated方法 @Component。但是,它们最常用于@Configuration豆类。

      对类进行注释@Configuration表明其主要目的是作为bean定义的来源。此外,@Configuration类允许通过调用@Bean同一类中的其他方法来定义bean间依赖关系。最简单的@Configuration类如下:

    1 @Configuration
    2 public class AppConfig {
    3 
    4     @Bean
    5     public MyService myService() {
    6         return new MyServiceImpl();
    7     }
    8 }

      上面的AppConfig类等效于以下Spring <beans/>XML:

    <beans>
        <bean id="myService" class="com.acme.services.MyServiceImpl"/>
    </beans>

      还可以@Bean使用接口(或基类)返回类型声明您的方法

      @Bean注释支持指定任意初始化和销毁回调方法

     1 public class BeanOne {
     2 
     3     public void init() {
     4         // initialization logic
     5     }
     6 }
     7 
     8 public class BeanTwo {
     9 
    10     public void cleanup() {
    11         // destruction logic
    12     }
    13 }
    14 
    15 @Configuration
    16 public class AppConfig {
    17 
    18     @Bean(initMethod = "init")
    19     public BeanOne beanOne() {
    20         return new BeanOne();
    21     }
    22 
    23     @Bean(destroyMethod = "cleanup")
    24     public BeanTwo beanTwo() {
    25         return new BeanTwo();
    26     }
    27 }

      @ImportResource

      虽然Spring提倡零配置,但是还是提供了对xml文件的支持,这个注解就是用来加载xml配置的。例:@ImportResource({"classpath"})

      @Value

      值得注入。经常与Sping EL表达式语言一起使用,注入普通字符,系统属性,表达式运算结果,其他Bean的属性,文件内容,网址请求内容,配置文件属性值等等

     1 package com.test.spring.beanannotation.javabased;
     2 
     3 import org.springframework.beans.factory.annotation.Value;
     4 import org.springframework.context.annotation.Bean;
     5 import org.springframework.context.annotation.Configuration;
     6 import org.springframework.context.annotation.ImportResource;
     7 
     8 @Configuration
     9 @ImportResource("classpath:config.xml")
    10 public class StoreConfig {
    11     
    12     @Value("${jdbc.url}")
    13     private String url;
    14     @Value("${jdbc.password}")
    15     private String password;
    16     @Value("${jdbc.username}")
    17     private String username;
    18      
    19     @Bean
    20     public MyDriverManager myDriverManager() {
    21         return new MyDriverManager(url, username, password);
    22     }
    23      
    24 } 

      @Profile

      通过@Profile 注释,您可以指示当一个或多个指定的配置文件处于活动状态时,组件符合注册条件。使用前面的示例,按如下方式重写配置:

     1 @Configuration
     2 @Profile("development")
     3 public class StandaloneDataConfig {
     4 
     5     @Bean
     6     public DataSource dataSource() {
     7         return new EmbeddedDatabaseBuilder()
     8             .setType(EmbeddedDatabaseType.HSQL)
     9             .addScript("classpath:com/bank/config/sql/schema.sql")
    10             .addScript("classpath:com/bank/config/sql/test-data.sql")
    11             .build();
    12     }
    13 }

      如果@Configuration标记了类,则除非一个或多个指定的配置文件处于活动状态,否则将绕过与该类关联的@Profile所有@Bean方法和 @Import注释。如果a @Component或@Configurationclass被标记@Profile({"p1", "p2"}),则除非已激活配置文件'p1'或'p2',否则不会注册或处理该类。如果给定的配置文件以NOT运算符(!)作为前缀,则仅在配置文件未激活时才注册带注释的元素。例如,@Profile({"p1", "!p2"})如果配置文件“p1”处于活动状态或配置文件“p2”未激活,则会发生注册

  • 相关阅读:
    HDU 2544 最短路
    HDU 3367 Pseudoforest
    USACO 2001 OPEN
    HDU 3371 Connect the Cities
    HDU 1301 Jungle Roads
    HDU 1879 继续畅通工程
    HDU 1233 还是畅通工程
    HDU 1162 Eddy's picture
    HDU 5745 La Vie en rose
    HDU 5744 Keep On Movin
  • 原文地址:https://www.cnblogs.com/h--d/p/11438566.html
Copyright © 2011-2022 走看看