目录
在使用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等;
@Controller
@RequestMapping("/appointments")
public class AppointmentsController {
private AppointmentBook appointmentBook;
@Autowired
public AppointmentsController(AppointmentBook appointmentBook) {
this.appointmentBook = appointmentBook;
}
@RequestMapping(method = RequestMethod.GET)
public Map<String, Appointment> get() {
return appointmentBook.getAppointmentsForToday();
}
@RequestMapping(value="/{day}", method = RequestMethod.GET)
public Map<String, Appointment> getForDay(@PathVariable @DateTimeFormat(iso=ISO.DATE) Date day, Model model) {
return appointmentBook.getAppointmentsForDay(day);
}
@RequestMapping(value="/new", method = RequestMethod.GET)
public AppointmentForm getNewForm() {
return new AppointmentForm();
}
@RequestMapping(method = RequestMethod.POST)
public String add(@Valid AppointmentForm appointment, BindingResult result) {
if (result.hasErrors()) {
return "appointments/new";
}
appointmentBook.addAppointment(appointment);
return "redirect:/appointments";
}
}
value的uri值为以下三类:
A) 可以指定为普通的具体值;
B) 可以指定为含有某变量的一类值(URI Template Patterns with Path Variables);
C) 可以指定为含正则表达式的一类值( URI Template Patterns with Regular Expressions);
example B)
@RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
public String findOwner(@PathVariable String ownerId, Model model) {
Owner owner = ownerService.findOwner(ownerId);
model.addAttribute("owner", owner);
return "displayOwner";
}
example C)
@RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\d\.\d\.\d}.{extension:\.[a-z]}")
public void handle(@PathVariable String version, @PathVariable String extension) {
// ...
}
}
consumes:指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
@Controller
@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")
public void addPet(@RequestBody Pet pet, Model model) {
// implementation omitted
}
方法仅处理request Content-Type为“application/json”类型的请求。
produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
@Controller
@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, produces="application/json")
@ResponseBody
public Pet getPet(@PathVariable String petId, Model model) {
// implementation omitted
}
方法仅处理request请求中Accept头中包含了"application/json"的请求,同时暗示了返回的内容类型为application/json;
params:指定request中必须包含某些参数值是,才让该方法处理;
@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
@RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, params="myParam=myValue")
public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
// implementation omitted
}
}
仅处理请求中包含了名为“myParam”,值为“myValue”的请求;
headers:指定request中必须包含某些指定的header值,才能让该方法处理请求;
@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
@RequestMapping(value = "/pets", method = RequestMethod.GET, headers="Referer=http://www.ifeng.com/")
public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {
// implementation omitted
}
}
实例解释:如果要在浏览器访问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("不是老司机也可以学开车。");
}
}
@Component
用法:泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
作用:和前面@Service、@Repository、@Controller一样,只是它们比@Component更巨细化。
总结:
@Repository、@Service、@Controller注解是使被标注的组件成为Bean被Spring纳入管理,而Bean的名称可以通过他们的属性自定义@Repository为数据访问层使用,@Service为Service层使用
@Resource、@Autowired注解是使用已经被Spirng纳入管理的Bean。@Resource使用方式为ByName。@Autowired使用方式为ByType,结合@Qualifier使用可以变更为ByName。它们同样可以自定义调用的Bean名称