Spring常用注解的用法和作用理解

标注@Controller、@Service、@Repository、@Autowired、@Resource、@Component、@Qualifier在Spring中的作用和用法理解

在使用spring的时候这些标注都是必不可少的会用到。今天就总结一下它们各自的作用以及用法。

一、实例

  • 控制层
@Controller
@RequestMapping(value="/car")
public class Action{
    @Autowired
    private IocCarSrivice iocCarSrivice ;

    @RequestMapping(value="/carRun")
    public void carRun(){
        iocCarSrivice.run();
    }
}
  • service层
@Service
public class IocCarService{
    @Resource
    private IIocCarDao iIocCarDaoImpl;

    public void carRun(){
        iIocCarDaoImpl.run();
    }
}
  • Dao层
public interface IIocCarDao{
    void run();
}
  • Dao层实现类
@Repository
public class IIocCarDaoImpl implements IIocCarDao{

    @Override
    public void run(){
        System.out.println("老司机才可以开车。");
    }
}
  • 测试
package CarTest;

import java.util.Date;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.kq.domain.TransPayLog;
import com.kq.service.TransPayLogService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class CarTest{
    @Autowired
    private IocCarService iocCarService;
    @Test
    public void Test3_7(){
       iocCarService.carRun();
    }
}

输入:老司机才可以开车。

注:以上就是一个最简单的三层架构,如果是发布到Tomcat下面,服务器会按照@Controller标注让Spring Bean工厂自动注入控制层实例,然后浏览@RequestMapping上面的路径,就可以通过一系列标注访问Dao层。此处测试因为没有发布,所以直接使用手动注入(关于怎么手动注入可以参考CarTest类上面的注解,或者直接使用BeanFactory)。

下面以上为例解释注解(在所有配置文件都齐全的情况下)

@Controller

   用法:标记于一个类上面
   作用:用来注解这个bean(类)是MVC模型中的一个控制层,使分发处理器识别到该类,该类会被spring的auto-scan扫到纳入管理。通俗来,被这个标注类里面的方法加上@RequestMaping(“…”),就可以直接被浏览器调用然后做一些数据逻辑处理。
   实例解释:如果要在浏览器访问Action类中的carRun方法(本地)127.0.0.1:8080/car/carRun

@RequestMaping

   用法:1.标记于一个被@Controller标注的类上
      2.标记于被@Controller标注类里面的方法上面
   作用:用法1,表示该被标注类下面所有方法的父类标注(可以理解为所有用法2“继承”用法1)@RequestMaping有六个属性value、method、consumes、produces、params、headers
   value:指定浏览器请求的地址;
   method:指定请求的method类型, GET、POST、PUT、DELETE等;
   consumes:指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
   produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
   params:指定request中必须包含某些参数值是,才让该方法处理;
   headers:指定request中必须包含某些指定的header值,才能让该方法处理请求;
   实例解释:如果要在浏览器访问Action类中的carRun方法,只需要本地域名+端口号+该标注所定义的value值即可(127.0.0.1:8080/car/carRun)  
   @RequestMaping常用的记住value和method,更详细的介绍——》链接

@Service

   用法:用于标注业务层组件(Service层)上
   作用:标注于业务层组件上表示定义一个bean,自动根据所标注的组件名称实例化一个首字母为小写的bean。
   实例解释:IocCarService类被标注为一个bean,bean名称为iocCarService,此时该类已经被spring纳入管理中,待使用

@Resource

   用法:标注于字段上或者setter方法上,@Resource默认按ByName进行自动装配
   作用:用来自动装配Bean,激活一个命名资源的依赖注入。@Resource属性name可以定义被自动装配Bean的名称
   实例解释:在IocCarService类中IIocCarDao 的实现类已经被@Repository标注为一个被Spring管理的Bean,此时需要用到它的时候只需要在属性名称上标注@Resource用户自动装配就可以了。
   
   情况1: 如果加上如下代码,打印输出的还是:只有老司机才可以开车。

@Repository
public class IIocCarDaoImplXXX implements IIocCarDao{

    @Override
    public void run(){
        System.out.println("不是老司机也可以学开车。");
    }
}

   这就很奇怪了,两个实现类。程序怎么知道我要调用哪一个呢。
因为在CarService类中我们的属性名(private IIocCarDao iIocCarDaoImpl;)是iIocCarDaoImpl而不是刚刚加入的iIocCarDaoImplXXX 所以打印出来的也就是只有老司机才可以开车。

   情况2:如果CarServicer类中我们将属性名改变(private IIocCarDao iIocCarDaoImplYYY;)
那么此时会报错(org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.ulewo.ioc.IIocCarDaoImplYYY] is defined: expected single matching bean but found 2: iIocCarDaoImpl,iIocCarDaoImplXXX),意思是程序找到两个Bean,名称为iIocCarDaoImpl和iIocCarDaoImplXXX,但是没有我们的iIocCarDaoImplYYY,所以报错了。
   此时解决方案可以使改变属性名称,还可以在@Resource注解上面给其定义正确的名称,如这样:

@Service
public class IocCarService{
    @Resource(name="iIocCarDaoImplYYY")
    private IIocCarDao iIocCarDaoImpl;

    public void carRun(){
        iIocCarDaoImpl.run();
    }
}

此时将会输出:不是老司机也可以学开车。

@Autowired

   该注解和@Resource的用法和作用基本一致。
   
   不同点:1. @Resource属于J2EE,@Autowired属于Spring
       2.@Autowired是根据类型(ByType)进行自动装配的
       3.@Autowired没有name属性,如果要按名称进行装配,需要配合@Qualifier使用
       

@Service
public class IocCarService{
    @Resource(name="iIocCarDaoImplYYY")
    private IIocCarDao iIocCarDaoImpl;

    public void carRun(){
        iIocCarDaoImpl.run();
    }
}
//等价于
@Service
public class IocCarService{
    @Autowired
    @Qualifie("iIocCarDaoImplYYY")
    private IIocCarDao iIocCarDaoImpl;

    public void carRun(){
        iIocCarDaoImpl.run();
    }
}

@Repository

   用法:用户标注数据访问层组件(Dao层)
   作用:实现Dao访问;将类识别为Bean,同时它将所标注的类中抛出的数据访问异常封装为 Spring 的数据访问异常类型。
   实例解释:Dao层实现类IIocCarDaoImpl 被Spring装载为bean纳入管理中,bean名称为iIocCarDaoImpl。 同时它将所标注的类中抛出的数据访问异常封装为 Spring 的数据访问异常类型。
   如果需要自定义Bean名称只需要改变该注解的value属性值
   

@Repository(value="IIocCarDaoImplZZZ")
public class IIocCarDaoImpl implements IIocCarDao{

    @Override
    public void run(){
        System.out.println("不是老司机也可以学开车。");
    }
}

此时如果按ByName使用这个bean,在@Resource或者@Autowired下面的属性名称将变为iIocCarDaoImplZZZ或者@Resource(name=”iIocCarDaoImplZZZ”)或者@Autowired+@Qualifie(“iIocCarDaoImplZZZ”)

@Component

   用法:泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
   作用:和前面@Service、@Repository、@Controller一样,只是它们比@Component更巨细化。


总结下:
   @Repository、@Service注解是使被标注的组件成为Bean被Spring纳入管理,而Bean的名称可以通过他们的属性自定义@Repository为数据访问层使用,@Service为Service层使用
   @Resource、@Autowired注解是使用已经被Spirng纳入管理的Bean。@Resource使用方式为ByName。@Autowired使用方式为ByType,结合@Qualifier使用可以变更为ByName。它们同样可以自定义调用的Bean名称

你可能感兴趣的:(java,基础)