H__D  

注释是否比配置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”未激活,则会发生注册

 

posted on 2019-08-31 12:23  H__D  阅读(360)  评论(0编辑  收藏  举报