• 【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”未激活,则会发生注册

  • 相关阅读:
    7387. 【2021.11.16NOIP提高组联考】数析送命题
    js 数组的基本操作
    界面跳转已打开界面强制刷新
    Topshelf安装Windows服务
    np_utils.to_categorical
    SQLServer数据库的.ldf文件太大怎办?
    Maven报错Please ensure you are using JDK 1.4 or above and not a JRE解决方法!
    [学习笔记]设计模式之Factory Method
    [学习笔记]设计模式之Singleton
    [学习笔记]设计模式之Abstract Factory
  • 原文地址:https://www.cnblogs.com/h--d/p/11438566.html
Copyright © 2020-2023  润新知