zoukankan      html  css  js  c++  java
  • Spring注解@Component、@Repository、@Service、@Controller @Resource、@Autowired、@Qualifier 解析

    URL:http://www.ulewo.com/user/10001/blog/273

    我们在使用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的名称就行,就不会错乱。

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

  • 相关阅读:
    几种委托的解释
    Python中的编码风格
    Python的循环
    Python中操作文件
    Python的random模块、string模块、time模块、os模块
    Python中的函数
    Python的数据类型
    使用iview Form 的resetFields()在f12下报错
    滚动条的滚动距离
    编程学习之资源
  • 原文地址:https://www.cnblogs.com/jqmtony/p/6794121.html
Copyright © 2011-2022 走看看