Spring注解学习
一、@Controller
标识一个该类是Spring MVC Controller处理器,用来创建处理http请求的对象。
@Controller public class TestController { @RequestMapping ("/test") public String test(Map<String,Object> map) { return "hello"; } }
二、@RestController
@RestController是Spring4之后加入的注解,原来在@Controller中返回json需要@ResponseBody来配合,如果直接使用@RestController来代替@Controller则不需要@ResponseBody,默认返回json格式。
三、@Service
标注业务层组件,将类注入到spring配置中。
四、@Autowired
用在JavaBean中的注解,通过byType形式,用来给指定的字段或方法注入所需的外部资源。默认情况下必须要求依赖对象存在,如果要允许为null,可以设置它的required属性为false.
@Autowired(required=false)
五、@RequestMapping
1、类定义处:提供初步的请求映射信息,相对于WEB应用的根目录。
2、方法处:提供进一步的细分映射信息,相对于类定义处的URL。
@Controller @RequestMapping("/test") public class TestController { @RequestMapping ("/test") public String test(Map<String,Object> map) { return "hello"; } }
3、方法处:params属性设置请求映射参数范围。
@RequestMapping (value= "testParams" , params={ "param1=value1" , "param2" , "!param3" }) public String testParams() { System. out .println( "test Params" ); return "testParams" ; }
在上面的代码中params属性指定了三个请求参数,含义是参数param1的值必须等于value1,参数param2必须存在,值无所谓,参数param3必须不存在,只有当请求/testParams.do满足指定的三个参数条件的时候才能访问到该方法。
4、method属性限制了请求的方法。
@RequestMapping (value= "testMethod" , method= {RequestMethod. GET , RequestMethod. DELETE }) public String testMethod() { return "method" ; }
只有以GET或者DELETE方式请求/testMethod.do的时候才能访问到该方法。
5、headers属性
@RequestMapping (value= "testHeaders" , headers={ "host=localhost" , "Accept" }) public String testHeaders() { return "headers" ; }
只有当请求包含Accept信息,且请求的host为localhost的时候才能正确的访问到testHeaders方法。
六、@RequestParam
用于将请求参数区数据映射到功能处理方法的参数上。
public Resp test(@RequestParam Integer id) { return Resp.success(customerInfoService.fetch(id)); }
这个id就是要接收从接口传递过来的参数id的值,如果接口传递过来的参数名和接收的不一致,也可以使用value来指定。
public Resp test(@RequestParam(value="course_id") Integer id){ return Resp.success(customerInfoService.fetch(id)); }
其中course_id就是接口传递的参数,id就是映射course_id的参数名。
七、@ModelAttribute
1、标记在方法上
标记在方法上,会在每一个@RequestMapping标注的方法前执行,如果有返回值,则自动将该返回值加入到ModelMap中。
(1)在有返回的方法上:当ModelAttribute设置了value,方法返回的值会以这个value为key,以参数接受到的值作为value,存入到Model中,如下面的方法执行之后,最终相当于model.addAttribute("user_name",name);如果
@ModelAttribute没有自定义value,最终相当于model.addAttribute("name",name);
@ModelAttribute(value="user_name") public String before2(@RequestParam(required = false) String name, Model model){ System.out.println("进入了2:"+name); return name; }
(2)在没返回的方法上:需要手动model.add方法。
@ModelAttribute public void before(@RequestParam(required = false)Integer age,Model model){ model.addAttribute("age",age); System.out.println("进入了1:" + age); }
在当前类下建一个请求方法:
在浏览器中输入访问地址并加上参数:
http://localhost:8081/api/test/mod?name=我是小菜&age=12
最终输出如下:
进入了1:40
进入了2:我是小菜
进入mod
参数接受的数值{name=我是小菜;age=12}
model传过来的值:{age=40,user_name=我是小菜}
2、标记在方法的参数上
标记在方法的参数上,会将客户端传递过来的参数按名称注入到指定对象中,并且会将这个对象自动加入ModelMap中,便于View层使用。
@RequestMapping(value="/mod2") public Resp mod2(@ModelAttribute("user_name") String user_name, @ModelAttribute("name") String name, @ModelAttribute("age") Integer age, Model model){ System.out.println("进入mod2"); System.out.println("user_name:" + user_name); System.out.println("name:"+name); System.out.println("age:"+age); System.out.println("model:"+model); return Resp.success("1"); }
在浏览器中输入访问地址并且加上参数:
http://localhost:8081/api/test/mod2?name=我是小菜&age=12
输出结果:
进入了mod2
user_name:我是小菜
name: 我是小菜
age:40
model:{...}
结果可以看出,用在方法参数中的@ModelAttribute注解,实际上是一种接受参数并且自动放入Model对象中。
八、@Cacheable
用来标记缓存查询。可用于方法或者类中,当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。
参数 | 解释 | example |
value | 缓存的名称,在Spring配置文件中定义,必须制定至少一个 |
@Cacheable(value="mycache") @Cacheable(value={"cache1","cache2"}) |
key | 缓存的key,可以为空,如果指定,要求按照SpEL表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 | @Cacheable(value="testcache",key="#userName") |
condition | 缓存的条件,可以为空,使用SpEL编写,返回true或者false,只有为true才进行缓存 |
@Cacheable(value="testcache",condition="#userName.length()>2") @Cacheable(value="testcache",condition="#id=1") |
8.1、value属性指定Cache名称
value属性是必须指定的,其表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称,其可以是一个Cahce也可以是多个Cache,当需要指定多个Cache时其是一个数组。
@Cacheable("cache1")//Cache是发生在cache1上的 public User find(Integer id) { returnnull; } @Cacheable({"cache1", "cache2"})//Cache是发生在cache1和cache2上的 public User find(Integer id) { returnnull; }
8.2、使用key属性自定义key
key属性是用来指定Spring缓存方法的返回结果时对应的key的。该属性支持SpringEL表达式。如果没有指定该属性时,Spring将使用默认策略生成key。
自定义策略是指我们可以通过Spring的EL表达式来指定我们的key。这里的EL表达式可以使用方法参数及它们对应的属性。使用方法参数时我们可以直接使用"#参数名"或者"#p参数index"。
/** * key 是指传入时的参数 * */ @Cacheable(value="users", key="#id") public User find(Integer id) { returnnull; } // 表示第一个参数 @Cacheable(value="users", key="#p0") public User find(Integer id) { returnnull; } // 表示User中的id值 @Cacheable(value="users", key="#user.id") public User find(User user) { returnnull; } // 表示第一个参数里的id属性值 @Cacheable(value="users", key="#p0.id") public User find(User user) { returnnull; }
8.3、condition属性指定发生的条件
有时候我们可能并不希望缓存一个方法所有返回结果。通过condition属性可以实现这一功能。condition属性默认为空,表示将缓存所有的调用情形。其值是通过SpringEL表达式来指定的,当为true时表示进行缓存处理;
当为false时表示不进行缓存处理,即每次调用该方法时该方法都会执行一次。如下所示只有当user的id为偶数时才会进行缓存。
// 根据条件判断是否缓存 @Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0") public User find(User user) { System.out.println("find user by user " + user); return user; }
九、@CacheEvict
@CacheEvict是用来标注在需要清除缓存元素的方法或者类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。
@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。其中value、key和contdition的语义与@Cacheable对应的属性类似。即value表示清除操作是发生在哪些Cache上的(对应Cache的名称),key则表示需要清除的是哪个key,如果未指定则会使用默认策略生成的key,condition表示清除操作发生的条件。
9.1、allEntries属性
allEnties是boolean类型,表示是否要清除缓存中的所有元素。默认为false,表示不需要。当指定了allEntries为true时,Spring Cache将忽略指定的key。有的时候我们需要Cache一下清除所有的元素,这比一个一个清除元素更有效率。
@CacheEvict(value="users", allEntries=true) public void delete(Integer id) { System.out.println("delete user by id: " + id); }
9.2、beforeInvocation属性
清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvacation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。
@CacheEvict(value="users", beforeInvocation=true) public void delete(Integer id) { System.out.println("delete user by id: " + id); }
十、@Caching
@Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。
@Caching(cacheable = @Cacheable("users"), evict = { @CacheEvict("cache2"), @CacheEvict(value = "cache3", allEntries = true) }) public User find(Integer id) { returnnull; }
十一、@Resource
@Resource的作用相当于@Autowired,区别是@Autowired是按照byType自动注入,而@Resource默认按照byName自动注入。
@Resource有两个比较重要的属性,分别是name和type,Spring将@Resource注解的name属性解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
@Resource装配的顺序:
1.如果同时指定了name和type属性,则从spring上下问中找到唯一匹配的bean进行装配,如果没有找到,则会抛出异常。
2.如果指定了name属性,则从spring上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
3.如果指定type属性,则从spring上下文中找到类型匹配的唯一bean进行装配,找不到或者是找到多个,则抛出异常。
4.如果既没有指定name属性,也没有指定type属性,则默认是按照byName的方式进行装配;如果没有匹配,则返回一个原始的类型进行装配,如果匹配则自动装配。
使用区别:
1.@Resource和@Autowired都可以用来装配bean,都可以写在字段上或者是写在setter方法上。
2.@Autowired默认是按照byType进行装配的,所以默认情况下是必须依赖的对象存在,如果要允许为空,可以设置它的required属性为false,如果想使用byName进行装配,可以结合@Qualifier注解进行使用。
3. @Resource默认是按照byName进行装配的,名称可以通过name属性进行制定,如果没有指定name属性,注解写在字段上时,默认是取字段名作为名称进行查找。如果注解写在setter方法上则默认是取属性的名称进行装配,当找不到与名称匹配的bean时才按照类
型进行装配。但是值得注意的是,一旦指定了name属性,就会按照名称进行装配。
十二、@PostConstruct
@PostConstruct用来标记是在项目启动的时候执行的方法,用来修饰一个非静态的void()方法。也就是说在spring容器启动时执行,多用于一些全局配置、数据字典之类的加载,被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次,PostConstruct在构造函数之后,init()方法之前执行,PreDestroy()方法在destroy()方法执行之后执行。
十三、@PreDestory
@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destory()方法,被@PreDestroy修饰的方法会在destroy()方法之后,在Servlet被彻底卸载之前执行。
十四、@Repository
@Repository用于标注数据访问组件,即DAO组件
十五、@Component
@Component泛指组件,当组件不好归类的时候,可以选择使用这个注解。
十六、@Scope
@Scope用来配置Spring bean 的作用域,它标识bean的作用域。
默认值是单例
1、singleton:单例模式,全局有且仅有一个实例。
2、prototype: 原型模式,每次获取Bean的时候会有一个新的实例。
3、request:request表示每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效。
4、session: session作用域表示每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效。
5、global session: 只在portal应用中有用,给每一个global HTTP session新建一个Bean实例。
十七、@SessionAttributes
默认情况下Spring MVC 将模型中的数据存储到request域中,当一个请求结束后,数据就失效了。如果要跨页面使用,那么需要使用到session,而@SessionAttributes注解就可以使得模型中的数据存储一份到session域中。
参数:
1、names: 这是一个字符串数组,里面应写需要存储到session中数据的名称。
2、types:根据指定参数的类型,将模型中对应类型的参数存储到session中。
3、value: 和names是一样的。
@Controller @SessionAttributes(values={"names"},types={Integer.class}) public class ScopeService { @RequestMapping("/testSession") public String test(Map<String,Object> map) { map.put("names",Arrays.asList("a","b","c")); map.put("age",12); return "hello"; } }
十八、@Required
@Required注解作用于Bean的setter方法上,用于检查一个Bean的属性的值在配置期间是否被赋予或设置。、
示例:
applicationContext.xml中进行配置
<bean id="resultMessage" class="com.test.demo.ResultMessage"> <!--此处只设置了code属性,无message属性 --> <property name="code" value="001" /> </bean> <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
在code和message的setter方法上加上@Required注解
public class ResultMessage { private String code; private String message; public String getCode() { return code; } @Required public void setCode(String code) { this.code = code; } public String getMessage() { return message; } @Required public void setMessage(String message) { this.message = message; } }
测试:
@Controller public class Test{ @Autowired private ResultMessage message; @RequestMapping("/testRequired") public String testRequired(HttpServletRequest req, HttpServletResponse resp) { System.out.println(message); } }
结果: 抛出 BeanInitializationException
异常。
十九、@Qualifier
当创建多个具有相同类型的bean时,并且想要用一个属性只为它们其中一个进行装配,在这种情况下,可以使用@Qualifier注解和@Autowired注解通过指定装配bean来消除混乱。