`

(转载)关于Spring注解的一些知识点

阅读更多

 

##############################################################

 

很长时间没做web项目都把以前学的那点框架知识忘光了,今天把以前做的一个项目翻出来看一下发现用·@Component标记一个组件,而网上有的用@Service标记组件,我晕就查了一下资料:

Spring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository、@Service 和 @Controller。
在目前的 Spring 版本中,这 3 个注释和 @Component 是等效的,但是从注释类的命名上,很容易看出这 3 个注释分别和持久层、业务层和控制层(Web 层)相对应。
虽然目前这3 个注释和 @Component 相比没有什么新意,但 Spring 将在以后的版本中为它们添加特殊的功能。
所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用上述注解对分层中的类进行注释。

@Service用于标注业务层组件

@Controller用于标注控制层组件(如struts中的action)

@Repository用于标注数据访问组件,即DAO组件

@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

[java] view plaincopy
 
  1. @Service  
  2. public class VentorServiceImpl implements iVentorService {     
  3. }  
  4. @Repository  
  5. public class VentorDaoImpl implements iVentorDao {   
  6. }  

 

在一个稍大的项目中,如果组件采用xml的bean定义来配置,显然会增加配置文件的体积,查找以及维护起来也不太方便。 
Spring2.5为我们引入了组件自动扫描机制,他在类路径下寻找标注了上述注解的类,并把这些类纳入进spring容器中管理。
它的作用和在xml文件中使用bean节点配置组件时一样的。要使用自动扫描机制,我们需要打开以下配置信息:

代码

[html] view plaincopy
 
  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.                 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
  7.         http://www.springframework.org/schema/context  
  8.         http://www.springframework.org/schema/context/spring-context-2.5.xsd">   
  9.      
  10.     <context:component-scan base-package=”com.eric.spring”>     
  11. </beans>   

1.component-scan标签默认情况下自动扫描指定路径下的包(含所有子包),将带有@Component、@Repository、@Service、@Controller标签的类自动注册到spring容器。对标记了 Spring's @Required、@Autowired、JSR250's @PostConstruct、@PreDestroy、@Resource、JAX-WS's @WebServiceRef、EJB3's @EJB、JPA's @PersistenceContext、@PersistenceUnit等注解的类进行对应的操作使注解生效(包含了annotation-config标签的作用)。

 

getBean的默认名称是类名(头字母小写),如果想自定义,可以@Service(“aaaaa”)这样来指定。
这种bean默认是“singleton”的,如果想改变,可以使用@Scope(“prototype”)来改变。

可以使用以下方式指定初始化方法和销毁方法:

[java] view plaincopy
 
  1. @PostConstruct  
  2. public void init() {   
  3. }   
  4. @PreDestroy  
  5. public void destory() {   
  6. }   


 

注入方式:

把DAO实现类注入到action的service接口(注意不要是service的实现类)中,注入时不要new 这个注入的类,因为spring会自动注入,如果手动再new的话会出现错误,
然后属性加上@Autowired后不需要getter()和setter()方法,Spring也会自动注入。  

在接口前面标上@Autowired注释使得接口可以被容器注入,如:

[java] view plaincopy
 
  1. @Autowired  
  2. @Qualifier("chinese")  
  3. private Man man;   

当接口存在两个实现类的时候必须使用@Qualifier指定注入哪个实现类,否则可以省略,只写@Autowired。

 

##############################################################

 

标注类中:

@Service用于标注业务层组件,@Controller用于标注控制层组件(如struts中的action),@Repository用于标注数据访问组件,即DAO组件,而@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

 

标注属性、方法 @Autowired和@Resource:

 

@Autowired 与@Resource 都可以用来装配bean.  都可以写在字段上,或写在set方法上

 

@Autowired (srping提供的) 默认按类型装配

 

@Resource ( j2ee提供的 ) 默认按名称装配,当找不到(不写name属性)名称匹配的bean再按类型装配.

可以通过@Resource(name="beanName") 指定被注入的bean的名称, 要是指定了name属性, 就用 字段名 去做name属性值,一般不用写name属性.

@Resource(name="beanName")指定了name属性,按名称注入但没找到bean, 就不会再按类型装配了.

 

还有个比较重要的一点是@Resource不是单例的,而@Autowired则是单例的。所以在struts2中使用manager,需要标注时,我个人觉得最好是用@Resource

 

 

##############################################################

 

 Spring注解@Component、@Repository、@Service、@Controller @Resource、@Autowired、@Qualifier 解析

 

     我们在使用spring的时候经常会用到这些注解,那么这些注解到底有什么区别呢。我们先来看代码

同样分三层来看:

Action 层:

package com.ulewo.ioc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class IocAction {
    @Autowired
    private IocService service;
    
    public void add(){
        service.add();
    }
}

 

service层:(service就直接定义类了,没有定义接口,定义接口也是一样的)

package com.ulewo.ioc;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

@Service
public class IocService {
    @Resource
    private IIocDao iocDao;
    public void add(){
        iocDao.add();
    }
}

 

Dao层

先定义一个接口

package com.ulewo.ioc;

public interface IIocDao {
    public void add();
}

 

然后实现类:

package com.ulewo.ioc;

import org.springframework.stereotype.Repository;

@Repository
public class IocDao implements IIocDao{
    public void add(){
        System.out.println("调用了dao");
    }
}

 

然后spring的配置,这个配置就很简单了,因为是基于注解的,我们不需要再xml中来定义很多

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:jee="http://www.springframework.org/schema/jee"
   xmlns:tx="http://www.springframework.org/schema/tx"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xmlns:task="http://www.springframework.org/schema/task"
   xsi:schemaLocation="http://www.springframework.org/schema/beans 
                       http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
                       http://www.springframework.org/schema/tx 
                       http://www.springframework.org/schema/tx/spring-tx-3.2.xsd 
                       http://www.springframework.org/schema/jee 
                       http://www.springframework.org/schema/jee/spring-jee-3.2.xsd 
                       http://www.springframework.org/schema/context 
                       http://www.springframework.org/schema/context/spring-context-3.2.xsd
                       http://www.springframework.org/schema/aop 
                       http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
                       http://www.springframework.org/schema/task 
                       http://www.springframework.org/schema/task/spring-task-3.2.xsd">
    <context:annotation-config />
        <context:component-scan base-package="com.ulewo.ioc" >
    </context:component-scan>  
</beans>

让spring自动扫描包就行了。

然后是我们的测试类:

IocTest:

package com.ulewo.ioc;

import junit.framework.TestCase;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class IocTest extends TestCase{
    
    public void testIoc(){
        BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
        IocAction action = factory.getBean("iocAction", IocAction.class);
        action.add();
    }
}

运行后,我们会发现 控制台打印:调用了dao

 

@Component、@Repository、@Service、@Controller @Resource、@Autowired、@Qualifier 

这几个基本都用到了 除了 @Component  @Qualifier

 

我们观察会发现@Repository、@Service、@Controller 这几个是一个类型,其实@Component 跟他们也是一个类型的

Spring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository、@Service和@Controller 其实这三个跟@Component 功能是等效的

 

@Service用于标注业务层组件(我们通常定义的service层就用这个)

@Controller用于标注控制层组件(如struts中的action)

@Repository用于标注数据访问组件,即DAO组件

@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

 

这几个注解是当你需要定义某个类为一个bean,则在这个类的类名前一行使用@Service("XXX"),就相当于讲这个类定义为一个bean,bean名称为XXX; 这几个是基于类的,我们可以定义名称,也可以不定义,不定义会默认以类名为bean的名称(类首字母小写)。

 

然后我们在看后面的几个注解

@Resource、@Autowired、@Qualifier

当需要在某个类中定义一个属性,并且该属性是一个已存在的bean,要为该属性赋值我们就用着三个。我们看上面的代码可以看到这三个都是定义在一个属性上的,比如

@Resource
private IIocDao iocDao;
@Autowired
private IocService service;

那这几个到底有什么区别呢?

我们先看@Resource,它是javax.annotation.Resource; 这个包中,也就是说是javaEE中的,并不是spring中的

而且@Resource("xxx") 是可以定义bean名称的,就是说我这个属性要用那个bean来赋值。

 

@Autowired,它是org.springframework.beans.factory.annotation.Autowired 是这个包中,它是spring的包。

而且它没有@Autowired("xxx"),那我要为这个bean定义名称怎么办这个时候可以用@Qualifier("xxx") 这个也是spring中的。这个xxx定义bean名称有什么用呢?我们回头看下刚才的代码。

在IIocDao 这个接口中,我们定义的实现类IocDao 只有一个,好那么我们再定义一个实现类:

package com.ulewo.ioc;

import org.springframework.stereotype.Repository;

@Repository
public class IocDao2 implements IIocDao{
    public void add(){
        System.out.println("调用了dao2");
    }
}

其他不变,我们再运行:testIoc(),控制台打印出 调用了dao,所以在service层中

@Resource
private IIocDao iocDao;

这个iocDao 注入的是IocDao 这个实现。奇怪了,它怎么知道我要调用哪个实现呢?

好我们修改一下,把 private IIocDao iocDao;改一下,改成 private IIocDao iocDaox 把属性名改一下,再运行,会报错:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.ulewo.ioc.IIocDao] is defined: expected single matching bean but found 2: iocDao,iocDao2

错误很明显啊,有两个bean iocDao和iocDao2,但是我们的是iocDaox所以找不到了。所以可以看出来在用 @Repository注解来生成bean的时候,如果没有定义名称那么就会根据类名来生成。所以我们要调用第二个实现的时候可以 定义为private IIocDao iocDao2 。我们再运行:调用了dao2,所以可以根据属性名来区分,到底注入那个bean。但是有的人说,我不想定义bean名称跟类实现一样,我要定义其他的,那怎么玩呢,方法有2种:

 

第一种:我们在生成bean的时候就给bean定义个名称 

@Repository("myIocDao")
public class IocDao implements IIocDao{
    public void add(){
        System.out.println("调用了dao");
    }
}

当然@Service是一样的,这样就把这个实现定义为myIocDao了,而不是默认的类名 iocDao。

那么我们在使用这个bean的时候就要这么定义了:

@Resource
private IIocDao myIocDao;

运行 输出:调用了dao

如果你这里不是用的 myIocDao,你又多加了一个x,成了myIocDaox,你运行会是这样的:

 org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.ulewo.ioc.IIocDao] is defined: expected single matching bean but found 2: myIocDao,iocDao2

所以,要自定义bean的名称可以在类注解的时候指定。

 

第二种:在注入bean的时候指定名称:

先看@Resource

我们这么定义下:

@Resource(name="iocDao")
private IIocDao xx;

注意:

@Repository
public class IocDao implements IIocDao{
    public void add(){
        System.out.println("调用了dao");
    }
}

这里还是用会默认的,也就是这个实现对应的是 iocDao这bean。如果你要为这个类指定别名bean,@Repository("myIocDao"),那@Resource(name="myIocDao") 就要这么写了。就是这里的name要跟实现类对应的bean名称保持一致。private IIocDao xx; 这个属性名就随便写了。

运行:调用了dao

如果用Autowired就要这么写了

@Autowired
@Qualifier("iocDao")
private IIocDao xx;

因为Autowired 不能像Resource 那样带个参数指定一个name,就要用Qualifier来指定了。

 

而且还可以这么用

@Resource
@Qualifier("iocDao")
private IIocDao xx;

等同于

@Resource(name="iocDao")
private IIocDao xx;

 

记住一点:@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,如果发现找到多个bean,则,又按照byName方式比对,如果还有多个,则报出异常 而@Resource默认按 byName自动注入罢了。其实spring注解,最常用的还是根据名称,根据类型啊,构造方法啊,用的非常少。所以在多个实现的时候我们定义好bean的名称就行,就不会错乱。

 

说了这么多,不知道对着几个注解是不是了解多一点了呢,貌似这些注解 没有根本上的区别,就看你习惯怎么用了。拿代码多跑几次,然后根据自己的想法改改,你就明白这几个注解的用处啦。

 

 

##############################################################

 

 

 

分享到:
评论

相关推荐

    spring注解笔记

    ### Spring注解知识点详解 #### 1. Spring注解基础 在Spring框架中,注解是一种轻量级的依赖注入方式,能够简化配置并提高开发效率。在本节中,我们主要介绍几个Spring中常用的注解,它们分别是@Component、@...

    dwr+spring 注解方式

    下面将详细介绍如何通过注解实现DWR和Spring的集成以及相关知识点: 1. **Spring注解配置**: - `@Configuration`:标记一个类为Spring配置类,可替代传统的XML配置。 - `@ComponentScan`:用于扫描指定包下的...

    spring注解实例

    本文将深入探讨Spring注解注入的相关知识点,以及如何通过提供的压缩包文件进行实践学习。 **1. Spring注解概述** 在Spring框架中,注解提供了元数据的方式来配置bean,使得我们不再需要XML配置文件。常见的注解...

    Spring注解驱动开发.pdf

    ### Spring注解驱动开发知识点详解 #### 一、Spring注解驱动概述 Spring框架通过引入注解支持,极大地简化了Java EE应用的开发工作。它不仅提供了基础的依赖注入功能,还增强了对组件扫描的支持,使得开发者能够...

    我的博客spring注解概述的示例代码

    在本文中,我们将深入探讨Spring框架中的注解,特别是与`@Autowired`相关的知识点。`@Autowired`是Spring框架提供的一种依赖注入(Dependency Injection,DI)机制,它简化了对象之间的依赖关系管理,使得代码更加...

    spring知识点总结

    “知识点总结.xls”可能是一个整理好的Spring框架关键知识点的表格,可能包含了Spring的主要模块(如Core Container、Data Access/Integration、Web、AOP、Test等)、关键概念(如Bean、ApplicationContext、IoC容器...

    spring简单注解+log4j记录日志

    下面将详细介绍这两个知识点以及如何将它们结合使用。 首先,让我们深入理解Spring框架的注解。注解(Annotation)是Java语言的一个重要特性,它允许我们在代码中添加元数据,为编译器或运行时环境提供额外的信息。...

    spring注解aop demo

    Spring注解AOP(Aspect-Oriented ...以上就是关于Spring注解AOP的基本知识点,包括其核心概念、使用方法、示例以及实际应用场景。理解并熟练掌握这些内容,将有助于提升在开发过程中对系统行为的控制和维护能力。

    spring使用注解依赖jar

    在本主题中,我们将深入探讨"spring使用注解依赖jar"这一关键知识点,包括Spring框架如何通过注解来实现依赖注入,以及如何管理相关的jar包。 首先,Spring框架的核心特性之一就是依赖注入(Dependency Injection,...

    Spring Boot技术知识点:如何理解@ConfigurationProperties注解

    下面将详细介绍`@ConfigurationProperties`的使用方法、工作原理以及相关知识点。 1. **使用场景** - 当我们需要从配置文件中读取大量相关的属性时,如数据库连接信息、邮件服务器配置等。 - 需要将配置参数与...

    Spring注解.pdf

    在当今的软件开发领域,Spring框架是一个广泛使用的开源应用程序框架,用于简化企业级应用的开发。它提供了全面的编程和配置模型...通过上述的各个知识点的掌握,开发者能够更好地利用Spring框架,发挥出其强大的功能。

    Spring Boot技术知识点:如何使用@Validated注解来对邮箱字段进行数据校验

    Spring Boot技术知识点:如何使用@Validated注解来对邮箱字段进行数据校验

    使用 Spring 2.5 基于注解驱动的 Spring.pdf

    #### 核心知识点概览 在Spring 2.5版本中,框架显著增强了对注解的支持,特别是针对SpringMVC(Model-View-Controller)模块,引入了基于注解的配置方式。这一改进不仅简化了开发流程,提高了框架的灵活性与易用性...

    用XFire开发WebService+Spring注解

    【标题】"用XFire开发WebService+Spring注解"涉及的主要知识点是利用XFire框架创建Web服务,并结合Spring框架的注解进行服务的管理和集成。XFire是一个强大的Java Web Service实现,它允许开发者轻松地创建和消费...

    spring一些常用知识点

    在本文中,我们将深入探讨Spring框架的一些核心知识点,以帮助开发者更好地理解和应用这一强大的工具。 1. **依赖注入(Dependency Injection, DI)**:Spring的核心特性之一,它允许组件之间的依赖关系在运行时被...

    spring mvc+ibatis+spring注解

    总之,这个项目展示了如何结合Spring MVC、Ibatis以及Spring注解,构建一个完整的Web应用程序,实现了数据的CRUD操作,以及分页排序查询和用户登录验证等功能,所有这些都基于非XML的配置方式,利用注解提高了开发...

    对spring做java注解扩展

    在Java编程世界里,Spring框架是企业级应用开发的首选工具,它以其强大的依赖注入(DI)和面向...对于`annotation-demo`这个示例项目,可能包含了上述概念的实际应用,你可以通过阅读源码进一步学习和实践这些知识点。

    非注解Springmvc+spring+hibernate 入门实例

    下面我们将深入探讨"非注解SpringMVC+Spring+Hibernate入门实例"中的关键知识点。 首先,让我们从SpringMVC开始。SpringMVC是一个Model-View-Controller架构模式的实现,用于构建Web应用程序。在非注解方式下,我们...

    2-Spring注解1

    【Spring注解1】知识点详解 1. **Spring注解介绍** Spring框架自3.0版本开始,引入了注解配置,逐渐成为主流的配置方式,减轻了XML配置的负担,使得代码更加简洁、易读。注解是元数据的一种形式,它允许在源代码...

Global site tag (gtag.js) - Google Analytics