浅析Spring中的注解

简介:

    Spring的配置,通常有两种:使用配置文件和注解。那么Spring如何知道各个Bean或者Service、Controller以及Bean中各类属性之间的关系呢?答案肯定是在定义各个Java文件的时候使用了各种注解,它们交织在一起,实现了使用配置文件完成的配置功能。

一、Bean相关的注解

    与SpringBean相关的注解有以下四大类:

  • @Component:标注一个普通的Spring Bean类

  • @Controller:标注一个控制器组件类

  • @Service:标注一个业务逻辑组件类

  • @Repository:标注一个DAO组件类

    如果我们需要定义一个普通的Spring Bean,那么直接使用@Component标注即可。但如果用@Repository、@Service或者@Controller来标注,那么这个Bean类将被作为特殊的JavaEE组件来对待。在Spring的未来版本中,@Controller、@Service和@Repository也许还能携带更多的语义,因此,如果需要在JavaEE应用中使用这些注解时,尽量考虑使用@Controller、@Service和@Repository来代替普通的@Component注解。例如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Scope ( "prototype" )
@Component ( "pp" )
public  class  People {
     private  int  age;
     private  String name;
     //省略getter和setter
}
 
@Service
public  class  PeopleService {
     @Autowired
     private  PeopleRepo peopleDao;
     
     public  void  addPeople(People p) {
         //other business logic here
         //...call method in PeopleRepo to complete
     }
     //省略 peopleDao的setter和getter
}
 
@Repository
public  class  PeopleRepo {
     public  void  addPeople(PeopleEntity p) {
         //...insert data only
     }
}

    指定了某些类可以作为Spring Bean后,还需要为Spring指定Bean的搜索路径,便于Spring自动在这个路径下搜索相关的Bean。在指定这个(或这些,如果有多个的话)路径之前,需要在Spring配置文件中导入context Schema:

?
1
2
3
4
5
6
7
8
9
10
11
12
<!-- 第4,6,7行是用于导入context Schema的 -->
< beans  xmlns=" 
     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/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd">
     
     <!-- 指定Spring将要扫描的包 -->
     < context:component-scan  base-package = "com.abc.model"  />
     < context:component-scan  base-package = "com.abc.service"  />
</ bean >

    上面的配置文件中的 comtext:component-scan指定了Spring将把com.abc.model包和com.abc.service包作为扫描目录,搜索其中带了@Component、@Controller、@Repository和@Service等注解的类作为容器中的Bean(某些是特殊的Bean)。

    在基于XML配置方式下,每个Bean实例的名称都由其id属性指定,而在使用注解配置Spring的方式下,Spring将采用约定的方式来为这些Bean实例指定名称,这些Bean实例的名称默认是Bean类的首字母小写,其他部分不变。 当然,Spring也允许使用@Component注解时自定义Bean的名字,如上面的People的注解@Component("pp"),意为把People的Bean实例命名为“pp”。

    当使用XML配置Bean时,可以通过scope来指定Bean的作用域,在使用注解时,可通过@Scope注解来标注,只要在该注解中提供作用域的名称即可。例如上面的:

?
1
2
3
4
5
6
7
@Scope ( "prototype" )
@Component ( "pp" )
public  class  People {
     private  int  age;
     private  String name;
     //省略getter和setter
}

    另外,我们还可以通过为<component-scan>元素添加<include-filter>和<exclude-filter>子元素来限制Spring Bean的类。满足<include-filter>定义的规则的Java类,才会被当作Bean处理,满足<exclude-filter>规则的Java类,则不会当作Bean处理。使用这两个属性时,都需要为其指定下面两个元素:

  • type:指定过滤器类型

  • expression:知道你过过滤器所需要的表达式

    Spring支持以下几种过滤器:

  • annotation:Annotation过滤器,该过滤器需要指定一个Annotation名

  • assignable:类名过滤器,该过滤器直接指定一个Java类

  • regex:正则表达式过滤器,该过滤器指定一个正则表达式,匹配该正则表达式的Java类将满足该过滤规则。如:com\.abc\.*

  • aspectj:AspectJ过滤器

?
1
2
3
4
5
<!-- 指定Spring将要扫描的包 -->
< context:component-scan  base-package = "com.abc.model" >
     < context:include-filter  type = "regex"  expression = ".*Peo*"  />
     < context:exclude-filter  type = "regex"  expression = ".*PPP*"  />
</ context:component-scan >

    

二、使用@Resource配置依赖

    @Resource注解位于java.annotation包下,是来自JavaEE规范中的一个注解,Spring直接借鉴了该注解,其作用是为目标Bean指定协作者Bean。

    @Resource有一个name属性,在默认情况下,Spring将这个值解释为需要被注入的Bean实例的名字。换句话说:使用@Resource与配置文件中<property>中的ref属性有相同的效果。例如:

?
1
2
3
4
5
6
7
8
@Component
public  class  People {
     private  Work work;
     @Resource (name= "computerWork" )
     public  void  setWork(Work work) {
         this .work = work;
     }
}

    上例就是将“computerWork”注入该setWork方法,也就是将容器中的computerWork作为setWork()方法的参数传入。

    @Resource方法不仅可以修饰setter方法,还可以直接修饰Field。如果使用@Resource修饰Field将更加简单,此时Spring将直接使用JavaEE中规范的Field注入,此时连setter方法都可以不要,例如可以将刚刚的例子改写为:

?
1
2
3
4
5
6
@Component
public  class  People {
     @Resource (name= "computerWork" )
     private  Work work;
     //do not need setter anymore
}

    使用@Resource注解时,其name属性也可以省略,默认情况下,name属性是该setter方法去掉set子串后,再将首字母小写得到的值。例如:使用@Resource标注setWork方法,则Spring默认会注入容器中名为work的组件。

    当使用@Resource标注一个Field时,如果省略name属性,则name属性默认与被标注的Field同名。例如:使用@Resource标注private Work work域,则Spring将把容器中名为work的组件注入。


三、使用@PostConstruct和@PreDestroy定制Bean的生命周期行为

    @PostConstruct和@PreDestroy两个注解同样位于java.annotation包下,也是来自JavaEE规范的注解,Spring也借鉴了它们,用于定制Spring容器中Bean的生命周期行为。这里介绍了Spring中的Bean可以指定init-method和destroy-method属性,而@PostConstruct和@PreDestroy的作用与此大致相似,他们都用于修饰方法,无需任何属性。其中前者修饰的方法是Bean的初始化方法;而后者修hi的方法是Bean销毁之前将要调用的方法。例如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Component
public  class  People {
     @Resource (name= "computerWork" )
     private  Work work;
     
     @PostConstruct
     public  void  init() {
         //...other operations here
         System.out.println( "init方法:所有依赖注入完成" );
     }
     
     @PreDestroy
     public  void  destroy() {
         //...other operations here
         System.out.println( "destroy方法:销毁之前" );
     }
}


四、Spring3.0新增的注解

    Spring3.0增加了两个新的注解:@DependsOn和@Lazy ,其中@DependsOn用于强制初始化其他Bean,而@Lazy则用于指定该Bean是否取消预初始化。

    @DependsOn可以修饰Bean类或方法,使用该注解时可以指定一个字符串数组作为参数,每个数组元素对应一个强制初始化的Bean,例如:

?
1
2
3
4
5
6
7
8
@DependsOn ({ "computerWork" , "job" })
@Component
public  class  People {
     @Resource (name= "computerWork" )
     private  Work work;
     @Resource (name= "job" )
     private  Job job;
}

    上面的代码使用了@DependsOn修饰了People类,这就指定在初始化People Bean之前,会强制初始化computerWork和job两个Bean。

    @Lazy注解主要用于修饰Spring Bean类,用于指定该Bean的预初始化行为,使用该注解时可以指定一个bool类型的值,该属性决定是否预初始化这个Bean。如果该值为true,则表示该Bean不会预初始化。例如:

?
1
2
3
4
5
@DependsOn ( true //这个Bean不会预初始化
@Component
public  class  People {
     //....
}


五、自动装配与精确装配

    Spring提供了@Autowired注解来指定自动装配,使用@Autowired可以标注setter方法,普通方法,Field和构造器等。例如:

?
1
2
3
4
5
6
7
8
9
@Component
public  class  People {
     private  Work work;
     
     @Autowired
     public  void  setWork(Work work) {
         this .work = work;
     }
}

    上面的代码使用了@Autowired指定对setWork()方法进行自动装配,Spring会将自动搜索器中类型为Work的Bean实例,并将该Bean实例作为setWork()方法的参数传入,注入给People实例。由此可见,当使用@Autowired注解标注setter方法时,默认使用的是byType的自动装配策略。

    Spring允许使用@Autowired来标注同时注入多个参数的普通方法,例如:

?
1
2
3
4
5
6
7
8
9
10
11
@Component
public  class  People {
     private  Work work;
     private  Job job;
     
     @Autowired
     public  void  init(Work work, Job job) {
         this .work = work;
         this .job = job;
     }
}

    使用@Autowired来标注Field和构造器的例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@Component
public  class  People {
     @Autowired
     private  School school;
     private  Work work;
     private  Job job;
     
     @Autowired
     public  People(Work work, Job job) {
         this .work = work;
         this .job = job;
     }
}

    当使用@Autowired来标注一个Field时,Spring将会把容器中与该Field类型匹配的Bean注入该属性。例如程序中使用@Autowired标注了school属性,则Spring会自动搜索容器中的School实例,并将该实例设置成该school Field的值;如果此时容器中不止一个School类型的Bean,则Spring将抛出一个BeanCreateException异常。

    @Autowired甚至可以用来修饰数组:

?
1
2
3
4
5
@Component
public  class  People {
     @Autowired
     private  School[] schools;
}

    在这种情况下,Spring将会搜集容器中所有类型为School的Bean,并用这些Bean创建一个数组,最后将这个数组注入给People的schools属性。与此类似的是,@Autowired也可以标注集合Field,或标注形参类型是集合的方法,Spring对这种集合属性,集合形参的处理与前面数组的处理是完全相同的。例如:

?
1
2
3
4
5
6
7
8
9
10
11
@Component
public  class  People {
     @Autowired
     private  Set<School> schools;
     
     private  Set<Work> works;
     @Autowired
     public  void  setWorks(Set<Work> works) {
         this .works = works;
     }
}

    对于这种集合类型的参数而言,程序代码中必须使用泛型,正如上面的程序所示,程序制定了该方法参数是Set<Work>类型,这表明,Spring会自动搜索容器中所有的Work类型实例,并将这些示例注入到到works属性中。如果程序中没有使用泛型来指明集合元素类型, 则Spring将不知所措。

    正如上面看到的,@Autowired总是采用byType的自动装配策略,在这种策略下,符合自动装配的类型的候选Bean常常有多个,这个时候就可能引起异常了(对于数组,集合类型的参数则不会)。

    为了实现精确的自动装配,Spring提供了@Qualifier注解,通过使用这个注解,允许Bean标识来指定自动装配。通常会为@Qualifier指定一个名字,表示精确定位id为这个名字的Bean,@Qualifier通常用于修饰Field,例如:

?
1
2
3
4
5
6
7
8
9
10
11
@Component
public  class  People {
     @Autowired
     @Qualifier ( "juniorHighSchool" )
     private  School school;
     
     //setter
     public  void  setSchool(School school) {
         this .shool = school;
     }
}

    上面的配置文件中指定了school将使用自动装配,且精确指定了被装配的Bean实例名称为juniorHighSchool,这意味着如果Spring容器中有多个School类型的Bean,只会将一个名为juniorHighSchool的Bean注入进来。

    除此之外,Spring还允许使用@Qualifier来标注方法的形参,例如:

?
1
2
3
4
5
6
7
8
9
@Component
public  class  People {   
     private  School school;
     
     //setter
     public  void  setSchool( @Qualifier ( "juniorHighSchool" )School school) {
         this .shool = school;
     }
}

目录
相关文章
|
2月前
|
缓存 监控 Java
SpringBoot @Scheduled 注解详解
使用`@Scheduled`注解实现方法周期性执行,支持固定间隔、延迟或Cron表达式触发,基于Spring Task,适用于日志清理、数据同步等定时任务场景。需启用`@EnableScheduling`,注意线程阻塞与分布式重复问题,推荐结合`@Async`异步处理,提升任务调度效率。
513 128
|
2月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
407 0
|
2月前
|
Java 测试技术 API
将 Spring 的 @Embedded 和 @Embeddable 注解与 JPA 结合使用的指南
Spring的@Embedded和@Embeddable注解简化了JPA中复杂对象的管理,允许将对象直接嵌入实体,减少冗余表与连接操作,提升数据库设计效率。本文详解其用法、优势及适用场景。
291 126
|
3月前
|
XML JSON Java
Spring框架中常见注解的使用规则与最佳实践
本文介绍了Spring框架中常见注解的使用规则与最佳实践,重点对比了URL参数与表单参数的区别,并详细说明了@RequestParam、@PathVariable、@RequestBody等注解的应用场景。同时通过表格和案例分析,帮助开发者正确选择参数绑定方式,避免常见误区,提升代码的可读性与安全性。
|
1月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
355 2
|
2月前
|
XML Java 数据格式
常用SpringBoot注解汇总与用法说明
这些注解的使用和组合是Spring Boot快速开发和微服务实现的基础,通过它们,可以有效地指导Spring容器进行类发现、自动装配、配置、代理和管理等核心功能。开发者应当根据项目实际需求,运用这些注解来优化代码结构和服务逻辑。
288 12
|
2月前
|
Java 测试技术 数据库
使用Spring的@Retryable注解进行自动重试
在现代软件开发中,容错性和弹性至关重要。Spring框架提供的`@Retryable`注解为处理瞬时故障提供了一种声明式、可配置的重试机制,使开发者能够以简洁的方式增强应用的自我恢复能力。本文深入解析了`@Retryable`的使用方法及其参数配置,并结合`@Recover`实现失败回退策略,帮助构建更健壮、可靠的应用程序。
338 1
使用Spring的@Retryable注解进行自动重试
|
2月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
179 0
探索Spring Boot的@Conditional注解的上下文配置
|
2月前
|
智能设计 Java 测试技术
Spring中最大化@Lazy注解,实现资源高效利用
本文深入探讨了 Spring 框架中的 `@Lazy` 注解,介绍了其在资源管理和性能优化中的作用。通过延迟初始化 Bean,`@Lazy` 可显著提升应用启动速度,合理利用系统资源,并增强对 Bean 生命周期的控制。文章还分析了 `@Lazy` 的工作机制、使用场景、最佳实践以及常见陷阱与解决方案,帮助开发者更高效地构建可扩展、高性能的 Spring 应用程序。
129 0
Spring中最大化@Lazy注解,实现资源高效利用

热门文章

最新文章