零.前言
注解的分类
1.声明bean的注解
- @Component 组件,没有明确的角色
- @Service 在业务逻辑层使用(service层)
- @Repository 在数据访问层使用(dao层)
- @Controller 在展现层使用,控制器的声明(C)
2.注入bean的注解
- @Autowired:由Spring提供
- @Inject:由JSR-330提供
- @Resource:由JSR-250提供
- 都可以注解在set方法和属性上,推荐注解在属性上(一目了然,少写代码)。
3.java配置类相关注解
- @Configuration 声明当前类为配置类,相当于xml形式的Spring配置(类上)
- @Bean 注解在方法上,声明当前方法的返回值为一个bean,替代xml中的方式(方法上)
- @Component注解,表明这个类是一个bean(类上)
- @ComponentScan 用于对Component进行扫描,相当于xml中的(类上)
- @WishlyConfiguration 为@Configuration与@ComponentScan的组合注解,可以替代这两个注解
4.切面(AOP)相关注解
Spring支持AspectJ的注解式切面编程。
- @Aspect 声明一个切面(类上)
- 使用@After、@Before、@Around定义建言(advice),可直接将拦截规则(切点)作为参数。
- @After 在方法执行之后执行(方法上)
- @Before 在方法执行之前执行(方法上)
- @Around 在方法执行之前与之后执行(方法上)
- @PointCut 声明切点
- 在java配置类中使用@EnableAspectJAutoProxy注解开启Spring对AspectJ代理的支持(类上)
1、@Bean:方法级别的注解,主要用在@Configuration和@Component注解的类里,@Bean注解的方法会产生一个Bean对象,该对象由Spring管理并放到IoC容器中。引用名称是方法名,也可以用@Bean(name = "beanID")指定组件名
2、@Scope("prototype"):将组件的范围设置为原型的(即多例)。保证每一个请求有一个单独的action来处理,避免action的线程问题。
由于Spring默认是单例的,只会创建一个action对象,每次访问都是同一个对象,容易产生并发问题,数据不安全。
3、@Autowired:默认按类型进行自动装配。在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入@Autowired标注的变量中。
4、@Resource:默认按名称进行自动装配,当找不到与名称匹配的Bean时会按类型装配。
简单点说,就是,能够明确该类是一个控制器类组件的,就用@Controller;能够明确是一个服务类组件的,就用@Service;能够明确该类是一个数据访问组件的,就用@Repository;不知道他是啥或者不好区分他是啥,但是就是想让他动态装配的就用@Component。
@Controller、@Service、@Component、@Repository都是类级别的注解,如果一个方法也想动态装配,就用@Bean。
当我们想按类型进行自动装配时,就用@Autowired;当我们想按名称(beanID)进行自动装配时,就用@Resource;当我们需要根据比如配置信息等来动态装配不同的组件时,可以用getBean("beanID")。
一. Spring常用注解介绍及其使用方法
1、@Controller:用于标注控制器层组件
在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示。在SpringMVC 中提供了一个非常简便的定义Controller 的方法,你无需继承特定的类或实现特定的接口,只需使用@Controller 标记一个类是Controller ,然后使用@RequestMapping 和@RequestParam 等一些注解用以定义URL 请求和Controller 方法之间的映射,这样的Controller 就能被外界访问到。此外Controller 不会直接依赖于HttpServletRequest 和HttpServletResponse 等HttpServlet 对象,它们可以通过Controller 的方法参数灵活的获取到。
@Controller 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping 注解。@Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器。单单使用@Controller 标记在一个类上还不能真正意义上的说它就是SpringMVC 的一个控制器类,因为这个时候Spring 还不认识它。那么要如何做Spring 才能认识它呢?这个时候就需要我们把这个控制器类交给Spring 来管理。有两种方式:
(1)在SpringMVC 的配置文件中定义MyController 的bean 对象。
(2)在SpringMVC 的配置文件中告诉Spring 该到哪里去找标记为@Controller 的Controller 控制器。
2,@RequestMapping
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
RequestMapping注解有六个属性,下面我们把她分成三类进行说明(下面有相应示例)。
1、使用 @RequestMapping 来映射 Request 请求与处理器
方式一、通过常见的类路径和方法路径结合访问controller方法
方式二、使用uri模板
@Controller
@RequestMapping ( "/test/{variable1}" )
public class MyController {
@RequestMapping ( "/showView/{variable2}" )
public ModelAndView showView( @PathVariable String variable1, @PathVariable ( "variable2" ) int variable2) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName( "viewName" );
modelAndView.addObject( " 需要放到 model 中的属性名称 " , " 对应的属性值,它是一个对象 " );
return modelAndView;
}
}
1、 value, method;
value: 指定请求的实际地址,指定的地址可以是URI Template 模式(后面将会说明);
method: 指定请求的method类型, GET、POST、PUT、DELETE等;
@RequestMapping (value= "testMethod" , method={RequestMethod. GET , RequestMethod. DELETE })
public String testMethod() {
return "method" ;
}
在上面的代码中就使用method 参数限制了以GET 或DELETE 方法请求/testMethod 的时候才能访问到该Controller 的testMethod 方法。
2、consumes,produces
consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
3、params,headers
params: 指定request中必须包含某些参数值是,才让该方法处理。
@RequestMapping (value= "testParams" , params={ "param1=value1" , "param2" , "!param3" })
public String testParams() {
System. out .println( "test Params..........." );
return "testParams" ;
}
用@RequestMapping 的params 属性指定了三个参数,这些参数都是针对请求参数而言的,它们分别表示参数param1 的值必须等于value1 ,参数param2 必须存在,值无所谓,参数param3 必须不存在,只有当请求/testParams.do 并且满足指定的三个参数条件的时候才能访问到该方法。所以当请求/testParams.do?param1=value1¶m2=value2 的时候能够正确访问到该testParams 方法,当请求/testParams.do?param1=value1¶m2=value2¶m3=value3 的时候就不能够正常的访问到该方法,因为在@RequestMapping 的params 参数里面指定了参数param3 是不能存在的。
headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。
@RequestMapping (value= "testHeaders" , headers={ "host=localhost" , "Accept" })
public String testHeaders() {
return "headers" ;
}
headers 属性的用法和功能与params 属性相似。在上面的代码中当请求/testHeaders.do 的时候只有当请求头包含Accept 信息,且请求的host 为localhost 的时候才能正确的访问到testHeaders 方法。
3、@Resource和@Autowired
@Qualifier(指定注入Bean的名称)
如果容器中有一个以上匹配的Bean,则可以通过@Qualifier注解限定Bean的名称
@Resource和@Autowired 都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包为javax.annotation.Resource,需要导入,但是Spring支持该注解的注入。
1、共同点
两者都可以写在字段和setter方法上。两者如果都写在字段上,那么就不需要再写setter方法。
2、不同点
(1)@Autowired
@Autowired为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired;只按照byType注入。
@Autowired注解是按照类型(byType)装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它的required属性为false。如果我们想使用按照名称(byName)来装配,可以结合@Qualifier注解一起使用。如下:
public class TestServiceImpl {
// 下面两种@Autowired只要使用一种即可
@Autowired
private UserDao userDao; // 用于字段上
@Autowired
public void setUserDao(UserDao userDao) { // 用于属性的方法上
this.userDao = userDao;
}
}
public class TestServiceImpl {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
}
(2)@Resource
@Resource默认按照ByName自动注入,由J2EE提供,需要导入包javax.annotation.Resource。@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。
public class TestServiceImpl {
// 下面两种@Resource只要使用一种即可
@Resource(name="userDao")
private UserDao userDao; // 用于字段上
@Resource(name="userDao")
public void setUserDao(UserDao userDao) { // 用于属性的setter方法上
this.userDao = userDao;
}
}
注:最好是将@Resource放在setter方法上,因为这样更符合面向对象的思想,通过set、get去操作属性,而不是直接去操作属性。
@Resource装配顺序:
①如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
②如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
③如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
④如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。
@Resource的作用相当于@Autowired,只不过@Autowired按照byType自动注入。
4、@Service:用于标注业务层组件
@Service对应的是业务层Bean,例如:
@Service("userService")
public class UserServiceImpl implements UserService {
………
}
@Service("userService")注解是告诉Spring,当Spring要创建UserServiceImpl的的实例时,bean的名字必须叫做"userService",这样当Action需要使用UserServiceImpl的的实例时,就可以由Spring创建好的"userService",然后注入给Action:在Action只需要声明一个名字叫"userService"的变量来接收由Spring注入的"userService"即可,具体代码如下:
// 注入userService
@Resource(name = "userService")
private UserService userService;
注意:在Action声明的"userService"变量的类型必须是"UserServiceImpl"或者是其父类"UserService",否则由于类型不一致而无法注入,由于Action中的声明的"userService"变量使用了@Resource注解去标注,并且指明了其name = "userService",这就等于告诉Spring,说我Action要实例化一个"userService",你Spring快点帮我实例化好,然后给我,当Spring看到userService变量上的@Resource的注解时,根据其指明的name属性可以知道,Action中需要用到一个UserServiceImpl的实例,此时Spring就会把自己创建好的名字叫做"userService"的UserServiceImpl的实例注入给Action中的"userService"变量,帮助Action完成userService的实例化,这样在Action中就不用通过"UserService userService = new UserServiceImpl();"这种最原始的方式去实例化userService了。如果没有Spring,那么当Action需要使用UserServiceImpl时,必须通过"UserService userService = new UserServiceImpl();"主动去创建实例对象,但使用了Spring之后,Action要使用UserServiceImpl时,就不用主动去创建UserServiceImpl的实例了,创建UserServiceImpl实例已经交给Spring来做了,Spring把创建好的UserServiceImpl实例给Action,Action拿到就可以直接用了。Action由原来的主动创建UserServiceImpl实例后就可以马上使用,变成了被动等待由Spring创建好UserServiceImpl实例之后再注入给Action,Action才能够使用。这说明Action对"UserServiceImpl"类的“控制权”已经被“反转”了,原来主动权在自己手上,自己要使用"UserServiceImpl"类的实例,自己主动去new一个出来马上就可以使用了,但现在自己不能主动去new "UserServiceImpl"类的实例,new "UserServiceImpl"类的实例的权力已经被Spring拿走了,只有Spring才能够new "UserServiceImpl"类的实例,而Action只能等Spring创建好"UserServiceImpl"类的实例后,再“恳求”Spring把创建好的"UserServiceImpl"类的实例给他,这样他才能够使用"UserServiceImpl",这就是Spring核心思想“控制反转”,也叫“依赖注入”,“依赖注入”也很好理解,Action需要使用UserServiceImpl干活,那么就是对UserServiceImpl产生了依赖,Spring把Acion需要依赖的UserServiceImpl注入(也就是“给”)给Action,这就是所谓的“依赖注入”。对Action而言,Action依赖什么东西,就请求Spring注入给他,对Spring而言,Action需要什么,Spring就主动注入给他。
5、@Component :
用于标注这是一个受 Spring 管理的组件,组件引用名称是类名,第一个字母小写。可以使用@Component(“beanID”) 指定组件的名称。
相当于通用的注解,当不知道一些类归到哪个层时使用,但是不建议。
6、@Repository:
用于标注数据访问组件,即DAO组件,用于注解dao层,在daoImpl类上面注解。