Spring注解注解解析

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

一样分三层来看:java

Action 层:spring

package com.ulewo.ioc;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;@Controllerpublic class IocAction {
    @Autowired    private IocService service;
    
    public void add(){
        service.add();
    }
}

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

package com.ulewo.ioc;import javax.annotation.Resource;import org.springframework.stereotype.Service;@Servicepublic class IocService {
    @Resource    private IIocDao iocDao;
    public void add(){
        iocDao.add();
    }
}

Dao层
测试

先定义一个接口
spa

package com.ulewo.ioc;public interface IIocDao {
    public void add();
}

而后实现类:
.net

package com.ulewo.ioc;import org.springframework.stereotype.Repository;@Repositorypublic class IocDao implements IIocDao{
    public void add(){
        System.out.println("调用了dao");
    }
}

而后spring的配置,这个配置就很简单了,由于是基于注解的,咱们不须要再xml中来定义不少
code

applicationContext.xmlcomponent

<?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自动扫描包就好了。orm

而后是咱们的测试类:

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,要为该属性赋值咱们就用着三个。咱们看上面的代码能够看到这三个都是定义在一个属性上的,好比

@Resourceprivate IIocDao iocDao;
@Autowiredprivate 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;@Repositorypublic 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的名称就行,就不会错乱。

相关文章
相关标签/搜索