浅析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;

    }

}

时间: 2024-10-31 06:43:43

浅析Spring中的注解的相关文章

Spring中的注解

  一.@Autowired注解(推荐使用@Resource) @Autowired可以对成员变量.方法和构造函数进行标注,来完成自动装配的工作.@Autowired的标注位置不同,它们都会在Spring在初始化这个bean时,自动装配这个属性.要使@Autowired能够工作,还需要在配置文件中加入 <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor&

spring中定时器的使用

在很多实际的web应用中,都有需要定时实现的服务,如每天12点推送个新闻,每隔一个小时提醒用户休息一下眼睛,隔一段时间检测用户是否离线等等. spring框架提供了对定时器的支持,通过配置文件就可以很好的实现定时器,只需要应用启动,就自动启动定时器.下面介绍一下具体做法. 第一种,使用XML配置的方法 前期工作,配置spring的开发环境(这里用到了spring的web应用包,需要导入) 首先创建定时器的任务类,定时器要做什么工作,就在这里写什么方法. package org.time; imp

Springboot中PropertySource注解的使用

摘要:本文重点讲解一下Spring中@PropertySource注解的使用,如何通过PropertySource注解加载指定的配置文件.以及PropertySource注解与@ConfigurationProperties两个注解的配合使用. 1.1. PropertySource注解加载指定的属性文件 Spring框架提供了PropertySource注解,目的是加载指定的属性文件,接下来我们看一下如何使用该注解.首先我们定义一个配置类,并在类中添加PropertySource注解,如下所示

Spring中我们用到的功能实现:基于注解的Ioc自动装配

  我们要完成自动装配,那么就要有一个存放bean对象的容器,然后要有装配的注解,那么哪些类该被存到容器呢,在spring中我们使用过@Service.@Resource等,看下面的代码,你也可以做到.     来看看这是一个简单的容器接口 /**  * 容器接口  * @author:rex  * @create_time:2014-6-26  * @version:V1.0  */ public interface Container { Object getBean(String name

Spring中应用反射机制浅析

我们知道,Spring中大量使用了反射机制,那么究竟是什么地方使用了呢?就从源头说起吧.   一  反射源头Class类 对类的概念我们已经非常熟悉了.比如可以有Student这个类,Person这个类.但是我们要知道,有一个叫Class的类,它是反射的源头.   正常方式:通过完整的类名->通过new实例化->取得实例化对象 反射方式:实例化对象->getClass()方法->通过完整的类名   一个简单的例子:   package cn.classes; public clas

spring中如何获取注入bean里方法上的注解?

问题描述 spring中如何获取注入bean里方法上的注解? 有这样一个需求,在spring中,想用反射获取一个注入bean中方法的注解 一般情况下这样的操作就行了: Method method = bean.getClass().getMethod(...); Annotation[] annotations = method.getAnnotations(); 这样就能获取注解了. 但在spring中,这种方法是获取不到annotation的,原因是这里的bean其实是一个代理类.那么问题来

详解Java的Spring框架中的注解的用法_java

1. 使用Spring注解来注入属性 1.1. 使用注解以前我们是怎样注入属性的 类的实现: class UserManagerImpl implements UserManager { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } ... } 配置文件: <bean id="userManagerImpl" class="com.

Spring中@Transactional事务回滚(含实例详细讲解,附源码)

版权声明:本文为博主原创文章,转载注明出处http://blog.csdn.net/u013142781 目录(?)[+] 一.使用场景举例 在了解@Transactional怎么用之前我们必须要先知道@Transactional有什么用.下面举个栗子:比如一个部门里面有很多成员,这两者分别保存在部门表和成员表里面,在删除某个部门的时候,假设我们默认删除对应的成员.但是在执行的时候可能会出现这种情况,我们先删除部门,再删除成员,但是部门删除成功了,删除成员的时候出异常了.这时候我们希望如果成员删

浅析Spring和MyBatis整合及逆向工程_java

spring和mybatis整合 整合思路 需要spring通过单例方式管理SqlSessionFactory. spring和mybatis整合生成代理对象,使用SqlSessionFactory创建SqlSession.(spring和mybatis整合自动完成) 持久层的mapper都需要由spring进行管理. 整合环境 创建一个新的java工程(接近实际开发的工程结构) jar包: mybatis3.2.7的jar包 spring3.2.0的jar包 mybatis和spring的整合