spring注解_spring注解详解 - CSDN
精华内容
参与话题
  • Java面试之Spring注解

    千次阅读 多人点赞 2019-08-06 14:31:30
    Spring的一个核心功能是IOC,就是将Bean初始化加载到容器中,Bean是如何加载到容器的,可以使用Spring注解方式或者Spring XML配置方式。 Spring注解方式减少了配置文件内容,更加便于管理,并且使用注解可以大大...

    Spring的一个核心功能是IOC,就是将Bean初始化加载到容器中,Bean是如何加载到容器的,可以使用Spring注解方式或者Spring
    XML配置方式。 Spring注解方式减少了配置文件内容,更加便于管理,并且使用注解可以大大提高了开发效率!

    在这里插入图片描述
    下面按照分类讲解Spring中常用的一些注解。

    主键类注解

    @Component :标准一个普通的spring Bean类。

    @Repository:标注一个DAO组件类。

    @Service:标注一个业务逻辑组件类。

    @Controller:标注一个控制器组件类。

    这些都是注解在平时的开发过程中出镜率极高,@Component、@Repository、@Service、@Controller实质上属于同一类注解,用法相同,功能相同,区别在于标识组件的类型。@Component可以代替@Repository、@Service、@Controller,因为这三个注解是被@Component标注的。

    在这里插入图片描述

    举例说明
    1)当一个组件代表数据访问层(DAO)的时候,我们使用@Repository进行注解,如下

    @Repository
    public class HappyDaoImpl implements HappyDao{
    private final static Logger LOGGER = LoggerFactory.getLogger(HappyDaoImpl .class);
    public void  club(){
            //do something ,like drinking and singing
        }
    }
    

    2)当一个组件代表业务层时,我们使用@Service进行注解,如下

    @Service(value="goodClubService")
    //使用@Service注解不加value ,默认名称是clubService
    public class ClubServiceImpl implements ClubService {
        @Autowired
        private ClubDao clubDao;
    
        public void doHappy(){
            //do some Happy
        }
     }
    

    3)当一个组件作为前端交互的控制层,使用@Controller进行注解,如下

    @Controller
    public class HappyController {
        @Autowired //下面进行讲解
        private ClubService clubService;
    
        // Control the people entering the Club
        // do something
    }
    /*Controller相关的注解下面进行详细讲解,这里简单引入@Controller*/
    

    总结注意点
    1、被注解的java类当做Bean实例,Bean实例的名称默认是Bean类的首字母小写,其他部分不变。@Service也可以自定义Bean名称,但是必须是唯一的!

    2、尽量使用对应组件注解的类替换@Component注解,在spring未来的版本中,@Controller,@Service,@Repository会携带更多语义。并且便于开发和维护!

    3、指定了某些类可作为Spring Bean类使用后,最好还需要让spring搜索指定路径,在Spring配置文件加入如下配置:

    <!-- 自动扫描指定包及其子包下的所有Bean类 -->
    <context:component-scan base-package="org.springframework.*"/>
    

    装配bean时常用的注解

    @Autowired:属于Springorg.springframework.beans.factory.
    annotation包下,可用于为类的属性、构造器、方法进行注值
    @Resource:不属于spring的注解,而是来自于JSR-250位于java.annotation包下,使用该annotation为目标bean指定协作者Bean。
    @PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作

    举例说明

    1):@Autowired
    源码

    @Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Autowired {
        boolean required() default true;
    }
    

    实例

    @Controller
    public class HappyController {
        @Autowired //默认依赖的ClubDao 对象(Bean)必须存在
        //@Autowired(required = false) 改变默认方式
        @Qualifier("goodClubService")
        private ClubService clubService;
    
        // Control the people entering the Club
        // do something
    }
    

    2):@Resource
    源码

    @Target({TYPE, FIELD, METHOD})
    @Retention(RUNTIME)
    public @interface Resource {
     String name() default "";
     Class type() default java.lang.Object.class;
     ...
    

    实例

    public class AnotationExp {
    
        @Resource(name = "HappyClient")
        private HappyClient happyClient;
    
        @Resource(type = HappyPlayAno .class)
        private HappyPlayAno happyPlayAno;
    }
    

    总结

    1):相同点
    @Resource的作用相当于@Autowired,均可标注在字段或属性的setter方法上。
    2):不同点
    a:提供方 @Autowired是Spring的注解,@Resource是javax.annotation注解,而是来自于JSR-250,J2EE提供,需要JDK1.6及以上。
    b :注入方式 @Autowired只按照Type 注入;@Resource默认按Name自动注入,也提供按照Type 注入;
    c:属性
    @Autowired注解可用于为类的属性、构造器、方法进行注值。默认情况下,其依赖的对象必须存在(bean可用),如果需要改变这种默认方式,可以设置其required属性为false。
    还有一个比较重要的点就是,@Autowired注解默认按照类型装配,如果容器中包含多个同一类型的Bean,那么启动容器时会报找不到指定类型bean的异常,解决办法是结合@Qualified注解进行限定,指定注入的bean名称。
    @Resource有两个中重要的属性:name和type。name属性指定byName,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。
    需要注意的是,@Resource如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时, @Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了。

    d:@Resource注解的使用性更为灵活,可指定名称,也可以指定类型 ;@Autowired注解进行装配容易抛出异常,特别是装配的bean类型有多个的时候,而解决的办法是需要在增加@Qualitied进行限定。

    Spring中 @Autowired注解与@Resource注解的区别

    注意点:使用@Resource也要注意添加配置文件到Spring,如果没有配置component-scan

    <context:component-scan> 
    <!--<context:component-scan>的使用,是默认激活<context:annotation-config>功能-->
    

    则一定要配置 annotation-config

    <context:annotation-config/>
    

    @Component vs @Configuration and @Bean

    简单介绍

    Spring的官方团队说@Component可以替代 @Configuration注解,事实上我们看源码也可以发现看到,如下

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component  //看这里!!!
    public @interface Configuration {
        String value() default "";
    

    虽然说可以替代但是两个注解之间还是有区别的!
    Bean注解主要用于方法上,有点类似于工厂方法,当使用了@Bean注解,我们可以连续使用多种定义bean时用到的注解,譬如用@Qualifier注解定义工厂方法的名称,用@Scope注解定义该bean的作用域范围,譬如是singleton还是prototype等。

    Spring 中新的 Java 配置支持的核心就是@Configuration 注解的类。这些类主要包括 @Bean 注解的方法来为 Spring 的 IoC 容器管理的对象定义实例,配置和初始化逻辑。

    使用@Configuration 来注解类表示类可以被 Spring 的 IoC 容器所使用,作为 bean 定义的资源。

    @Configuration
    public class AppConfig {
        @Bean
        public MyService myService() {
            return new MyServiceImpl();
        }
    }
    

    这和 Spring 的 XML 文件中的非常类似

    <beans>
        <bean id="myService" class="com.acme.services.MyServiceImpl"/>
    </beans>
    

    @Bean 注解扮演了和元素相同的角色。

    举例说明@Component 和 @Configuration

    @Configuration
    public static class Config {
    
        @Bean
        public SimpleBean simpleBean() {
            return new SimpleBean();
        }
    
        @Bean
        public SimpleBeanConsumer simpleBeanConsumer() {
            return new SimpleBeanConsumer(simpleBean());
        }
    }
    

    @Component
    public static class Config {

    @Bean
    public SimpleBean simpleBean() {
        return new SimpleBean();
    }
    
    @Bean
    public SimpleBeanConsumer simpleBeanConsumer() {
        return new SimpleBeanConsumer(simpleBean());
    }
    

    }

    第一个代码正常工作,正如预期的那样,SimpleBeanConsumer将会得到一个单例SimpleBean的链接。第二个配置是完全错误的,因为Spring会创建一个SimpleBean的单例bean,但是SimpleBeanConsumer将获得另一个SimpleBean实例(也就是相当于直接调用new SimpleBean() ,这个bean是不归Spring管理的),既new SimpleBean() 实例是Spring上下文控件之外的。

    总结

    使用@ configuration,所有标记为@ bean的方法将被包装成一个CGLIB包装器,它的工作方式就好像是这个方法的第一个调用,那么原始方法的主体将被执行,最终的对象将在spring上下文中注册。所有进一步的调用只返回从上下文检索的bean。
    在上面的第二个代码块中,新的SimpleBeanConsumer(simpleBean())只调用一个纯java方法。为了纠正第二个代码块,我们可以这样做

    @Component
    public static class Config {
        @Autowired
        SimpleBean simpleBean;
    
        @Bean
        public SimpleBean simpleBean() {
            return new SimpleBean();
        }
    
        @Bean
        public SimpleBeanConsumer simpleBeanConsumer() {
            return new SimpleBeanConsumer(simpleBean);
        }
    }
    

    Spring @Configuration vs @Component
    基本概念:@Configuration 和@Bean

    spring MVC模块注解

    web模块常用到的注解

    @Controller :表明该类会作为与前端作交互的控制层组件,通过服务接口定义的提供访问应用程序的一种行为,解释用户的输入,将其转换成一个模型然后将试图呈献给用户。

    @Controller
    public class HappyController {
        //do something
    ...
    }
    

    Spring MVC 使用 @Controller 定义控制器,它还允许自动检测定义在类路径下的组件(配置文件中配置扫描路径)并自动注册。

    @RequestMapping : 这个注解用于将url映射到整个处理类或者特定的处理请求的方法。可以只用通配符!

    @Controller
    @RequestMapping("/happy")
    public class HappyController  {
    
      @Autowired
      private HappyService happyService;
    
      @RequestMapping(/hello/*)
      public void sayHello(){
            //请求为 /happy/hello/* 都会进入这个方法!
            //例如:/happy/hello/123   /happy/hello/adb
            //可以通过get/post 请求
      }
      @RequestMapping(value="/haha",method=RequestMethod.GET)
      public void sayHaHa(){
      //只能通过get请求
      }
    

    @RequestMapping 既可以作用在类级别,也可以作用在方法级别。当它定义在类级别时,标明该控制器处理所有的请求都被映射到 /favsoft 路径下。@RequestMapping中可以使用 method 属性标记其所接受的方法类型,如果不指定方法类型的话,可以使用 HTTP GET/POST 方法请求数据,但是一旦指定方法类型,就只能使用该类型获取数据。

    @RequestParam :将请求的参数绑定到方法中的参数上,有required参数,默认情况下,required=true,也就是改参数必须要传。如果改参数可以传可不传,可以配置required=false。

     @RequestMapping("/happy")
      public String sayHappy(
      @RequestParam(value = "name", required = false) String name,
      @RequestParam(value = "age", required = true) String age) {
      //age参数必须传 ,name可传可不传
      }
    

    @PathVariable : 该注解用于方法修饰方法参数,会将修饰的方法参数变为可供使用的uri变量(可用于动态绑定)。

    @RequestMapping(value="/happy/{dayid}",method=RequestMethod.GET)
    public String findPet(@PathVariable String dayid, Model mode) {
    //使用@PathVariable注解绑定 {dayid} 到String dayid
    }
    

    @PathVariable中的参数可以是任意的简单类型,如int, long, Date等等。Spring会自动将其转换成合适的类型或者抛出 TypeMismatchException异常。当然,我们也可以注册支持额外的数据类型。
    @PathVariable支持使用正则表达式,这就决定了它的超强大属性,它能在路径模板中使用占位符,可以设定特定的前缀匹配,后缀匹配等自定义格式。

    @RequestBody : @RequestBody是指方法参数应该被绑定到HTTP请求Body上。
    @RequestMapping(value = "/something", method = RequestMethod.PUT)
    public void handle(@RequestBody String body,@RequestBody User user){
    

    //可以绑定自定义的对象类型
    }

    @ResponseBody : @ResponseBody与@RequestBody类似,它的作用是将返回类型直接输入到HTTP response body中。
    @ResponseBody在输出JSON格式的数据时,会经常用到。

    @RequestMapping(value = "/happy", method =RequestMethod.POST)
    @ResponseBody
    public String helloWorld() {    
    return "Hello World";//返回String类型
    }
    

    @RestController :控制器实现了REST的API,只为服务于JSON,XML或其它自定义的类型内容,@RestController用来创建REST类型的控制器,与@Controller类型。@RestController就是这样一种类型,它避免了你重复的写@RequestMapping与@ResponseBody。

    @ModelAttribute :@ModelAttribute可以作用在方法或方法参数上,当它作用在方法上时,标明该方法的目的是添加一个或多个模型属性(model attributes)。
    该方法支持与@RequestMapping一样的参数类型,但并不能直接映射成请求。控制器中的@ModelAttribute方法会在@RequestMapping方法调用之前而调用。

    @ModelAttribute方法有两种风格:一种是添加隐形属性并返回它。另一种是该方法接受一个模型并添加任意数量的模型属性。用户可以根据自己的需要选择对应的风格。

    Spring事务模块注解

    1、常用到的注解

    在处理dao层或service层的事务操作时,譬如删除失败时的回滚操作。使用@Transactional 作为注解,但是需要在配置文件激活

    <!-- 开启注解方式声明事务 -->
        <tx:annotation-driven transaction-manager="transactionManager" />
    
    

    2、举例

    @Service
    public class CompanyServiceImpl implements CompanyService {
      @Autowired
      private CompanyDAO companyDAO;
    
      @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
      public int deleteByName(String name) {
    
        int result = companyDAO.deleteByName(name);
        return result;
      }
      ...
    }
    
    

    总结

    事务的传播机制和隔离机制比较重要!
    在这里插入图片描述

    一图学习 Spring事务传播性

    readOnly : 事务的读写属性,取true或者false,true为只读、默认为false
    rollbackFor : 回滚策略,当遇到指定异常时回滚。譬如上例遇到异常就回滚
    timeout (补充的) : 设置超时时间,单位为秒
    isolation : 设置事务隔离级别,枚举类型,一共五种

    在这里插入图片描述

    透彻的掌握 Spring 中@transactional 的使用

    Spring事务配置及事务的传播性与隔离级别详解

    参考博文

    spring 常用注解
    详解Spring MVC 4常用的那些注解

    史上最全最强SpringMVC详细示例实战教程

    展开全文
  • 史上最全spring注解,没有之一

    万次阅读 多人点赞 2018-07-05 09:58:14
    注解是个好东西,但好东西我们也是看见过,整理过,理解过,用过才知道好。不求我们每个都记住,但求保有印象,在需要的时候能提取出来再查找相关资料,平时工作就不会显得那么被动了。1.@Configuration注解该类等价...

    注解是个好东西,但好东西我们也是看见过,整理过,理解过,用过才知道好。不求我们每个都记住,但求保有印象,在需要的时候能提取出来再查找相关资料,平时工作就不会显得那么被动了。

    1.@Configuration注解

    该类等价 与XML中配置beans,相当于Ioc容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean,与xml中配置的bean意思一样。

    @Configuration注解的类必需使用<context:component-scanbase-package=”XXX”/>扫描.如下:

    1. @Configuration  
    2. public class MainConfig {  
    3.   
    4. //在properties文件里配置  
    5.     @Value(“${wx_appid}”)  
    6. public String appid;  
    7.     
    8.      protected MainConfig(){}  
    9.   
    10.     @Bean  
    11.     public WxMpService wxMpService() {  
    12.         WxMpService wxMpService = new WxMpServiceImpl();  
    13.         wxMpService.setWxMpConfigStorage(wxMpConfigStorage());  
    14.         return wxMpService;  
    15. }  
    16. }  
    @Configuration
    public class MainConfig {
    
    //在properties文件里配置
        @Value("${wx_appid}")
    public String appid;
    
         protected MainConfig(){}
    
        @Bean
        public WxMpService wxMpService() {
            WxMpService wxMpService = new WxMpServiceImpl();
            wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
            return wxMpService;
    }
    }
    

    定义一个MainConfig,用@Configuration注解,那MainConfig相当于xml里的beans,里面用@Bean注解的和xml里定义的bean等价,用<context:component-scanbase-package=”XXX”/>扫描该类,最终我们可以在程序里用@AutoWired或@Resource注解取得用@Bean注解的bean,和用xml先配置bean然后在程序里自动注入一样。目的是减少xml里配置。


    2.@Value注解

    为了简化从properties里取配置,可以使用@Value, 可以properties文件中的配置值。

    在dispatcher-servlet.xml里引入properties文件。

    1. <context:property-placeholder location=“classpath:test.properties” />  
    <context:property-placeholder location="classpath:test.properties" />

    在程序里使用@Value:

    @Value(“${wx_appid}”)

    publicString appid;

    即使给变量赋了初值也会以配置文件的值为准。



    3. @Controller, @Service, @Repository,@Component

    目前4种注解意思是一样,并没有什么区别,区别只是名字不同。使用方法:

    1.使用<context:component-scanbase-package=”XXX”/>扫描被注解的类

    2. 在类上写注解:

    @Controller

    public class TestController {

     

    }

     


    4. @PostConstruct 和 @PreDestory 

    实现初始化和销毁bean之前进行的操作,只能有一个方法可以用此注释进行注释,方法不能有参数,返回值必需是void,方法需要是非静态的。

    例如:

    1. public class TestService {   
    2.   
    3.     @PostConstruct    
    4.     public void  init(){    
    5.         System.out.println(“初始化”);    
    6.     }    
    7.         
    8.     @PreDestroy    
    9.     public void  dostory(){    
    10.         System.out.println(“销毁”);    
    11.     }    
    12. }  
    public class TestService { 
    
        @PostConstruct  
        public void  init(){  
            System.out.println("初始化");  
        }  
    
        @PreDestroy  
        public void  dostory(){  
            System.out.println("销毁");  
        }  
    }
    

    @PostConstruct:在构造方法和init方法(如果有的话)之间得到调用,且只会执行一次。

    @PreDestory:注解的方法在destory()方法调用后得到执行。

    网上拷贝的流程图:


    引深一点,Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,常用的设定方式有以下三种:

    1.通过实现 InitializingBean/DisposableBean 接口来定制初始化之后/销毁之前的操作方法;

    2.通过 <bean> 元素的 init-method/destroy-method属性指定初始化之后 /销毁之前调用的操作方法;

    3.在指定方法上加上@PostConstruct 或@PreDestroy注解来制定该方法是在初始化之后还是销毁之前调用

    但他们之前并不等价。即使3个方法都用上了,也有先后顺序.

    Constructor > @PostConstruct >InitializingBean > init-method

     


    5. @Primary

    自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常。

    例如:

    1. @Component    
    2. public class Apple implements Fruit{    
    3.     
    4.     @Override    
    5.     public String hello() {    
    6.         return ”我是苹果”;    
    7.     }    
    8. }  
    9.   
    10. @Component    
    11. @Primary  
    12. public class Pear implements Fruit{    
    13.     
    14.     @Override    
    15.     public String hello(String lyrics) {    
    16.         return ”梨子”;    
    17.     }    
    18. }  
    19.    
    20. public class FruitService {   
    21.     
    22.   //Fruit有2个实例子类,因为梨子用@Primary,那么会使用Pear注入  
    23.     @Autowired    
    24.     private Fruit fruit;    
    25.     
    26.     public String hello(){    
    27.         return fruit.hello();    
    28.     }    
    29. }  
    @Component  
    public class Apple implements Fruit{  
    
        @Override  
        public String hello() {  
            return "我是苹果";  
        }  
    }
    
    @Component  
    @Primary
    public class Pear implements Fruit{  
    
        @Override  
        public String hello(String lyrics) {  
            return "梨子";  
        }  
    }
    
    public class FruitService { 
    
      //Fruit有2个实例子类,因为梨子用@Primary,那么会使用Pear注入
        @Autowired  
        private Fruit fruit;  
    
        public String hello(){  
            return fruit.hello();  
        }  
    }
    



    6. @Lazy(true)

        用于指定该Bean是否取消预初始化,用于注解类,延迟初始化。

     


    7. @Autowired

    Autowired默认先按byType,如果发现找到多个bean,则,又按照byName方式比对,如果还有多个,则报出异常。

    1.可以手动指定按byName方式注入,使用@Qualifier。

    //通过此注解完成从spring配置文件中 查找满足Fruit的bean,然后按//@Qualifier指定pean

    @Autowired

    @Qualifier(“pean”)

    public Fruit fruit;

    2.如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) 

    public Fruit fruit;

     


    8. @Resource

    默认按 byName自动注入,如果找不到再按byType找bean,如果还是找不到则抛异常,无论按byName还是byType如果找到多个,则抛异常。

    可以手动指定bean,它有2个属性分别是name和type,使用name属性,则使用byName的自动注入,而使用type属性时则使用byType自动注入。

    @Resource(name=”bean名字”)

    @Resource(type=”bean的class”)

    这个注解是属于J2EE的,减少了与spring的耦合。

     


    9. @Async

        java里使用线程用3种方法:

    1.  继承Thread,重写run方法

    2.  实现Runnable,重写run方法

    3.  使用Callable和Future接口创建线程,并能得到返回值。

    前2种简单,第3种方式特别提示一下,例子如下:

    1. class MyCallable implements Callable<Integer> {  
    2.     private int i = 0;  
    3.     // 与run()方法不同的是,call()方法具有返回值  
    4.     @Override  
    5.     public Integer call() {  
    6.         int sum = 0;  
    7.         for (; i < 100; i++) {  
    8.             System.out.println(Thread.currentThread().getName() + ” ” + i);  
    9.             sum += i;  
    10.         }  
    11.         return sum;  
    12.     }  
    13. }  
    class MyCallable implements Callable<Integer> {
        private int i = 0;
        // 与run()方法不同的是,call()方法具有返回值
        @Override
        public Integer call() {
            int sum = 0;
            for (; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + " " + i);
                sum += i;
            }
            return sum;
        }
    }
    


    main方法:

    1. public static void main(String[] args) {  
    2.         Callable<Integer> myCallable = new MyCallable();    // 创建MyCallable对象  
    3.         FutureTask<Integer> ft = new FutureTask<Integer>(myCallable); //使用FutureTask来包装MyCallable对象  
    4.         for (int i = 0; i < 100; i++) {  
    5.             System.out.println(Thread.currentThread().getName() + ” ” + i);  
    6.             if (i == 30) {  
    7.                 Thread thread = new Thread(ft);   //FutureTask对象作为Thread对象的target创建新的线程  
    8.                 thread.start();                      //线程进入到就绪状态  
    9.             }  
    10.         }  
    11.         System.out.println(“主线程for循环执行完毕..”);  
    12.         try {  
    13.             int sum = ft.get();            //取得新创建的新线程中的call()方法返回的结果  
    14.             System.out.println(“sum = ” + sum);  
    15.         } catch (InterruptedException e) {  
    16.             e.printStackTrace();  
    17.         } catch (ExecutionException e) {  
    18.             e.printStackTrace();  
    19.         }  
    20. }  
    public static void main(String[] args) {
            Callable<Integer> myCallable = new MyCallable();    // 创建MyCallable对象
            FutureTask<Integer> ft = new FutureTask<Integer>(myCallable); //使用FutureTask来包装MyCallable对象
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + " " + i);
                if (i == 30) {
                    Thread thread = new Thread(ft);   //FutureTask对象作为Thread对象的target创建新的线程
                    thread.start();                      //线程进入到就绪状态
                }
            }
            System.out.println("主线程for循环执行完毕..");
            try {
                int sum = ft.get();            //取得新创建的新线程中的call()方法返回的结果
                System.out.println("sum = " + sum);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
    }
    

    而使用@Async可视为第4种方法。基于@Async标注的方法,称之为异步方法,这个注解用于标注某个方法或某个类里面的所有方法都是需要异步处理的。被注解的方法被调用的时候,会在新线程中执行,而调用它的方法会在原来的线程中执行。

    application.xml形势的配置:

    第一步配置XML。

    1. <!–扫描注解,其中包括@Async –>  
    2. <context:component-scan base-package=“com.test”/>  
    3. <!– 支持异步方法执行, 指定一个缺省的executor给@Async使用–>  
    4. <task:annotation-driven executor=“defaultAsyncExecutor”  />   
    5. <!—配置一个线程执行器–>  
    6. <task:executor id=” defaultAsyncExecutor ”pool-size=“100-10000” queue-capacity=“10” keep-alive =”5”/>  
    <!--扫描注解,其中包括@Async -->
    <context:component-scan base-package="com.test"/>
    <!-- 支持异步方法执行, 指定一个缺省的executor给@Async使用-->
    <task:annotation-driven executor="defaultAsyncExecutor"  /> 
    <!—配置一个线程执行器-->
    <task:executor id=" defaultAsyncExecutor "pool-size="100-10000" queue-capacity="10" keep-alive =”5”/>
    

    参数解读:

    <task:executor />配置参数:

    id:当配置多个executor时,被@Async(“id”)指定使用;也被作为线程名的前缀。

    pool-size:

    core size:最小的线程数,缺省:1

    max size:最大的线程数,缺省:Integer.MAX_VALUE

    queue-capacity:当最小的线程数已经被占用满后,新的任务会被放进queue里面,当这个queue的capacity也被占满之后,pool里面会创建新线程处理这个任务,直到总线程数达到了max size,这时系统会拒绝这个任务并抛出TaskRejectedException异常(缺省配置的情况下,可以通过rejection-policy来决定如何处理这种情况)。缺省值为:Integer.MAX_VALUE

    keep-alive:超过core size的那些线程,任务完成后,再经过这个时长(秒)会被结束掉

    rejection-policy:当pool已经达到max size的时候,如何处理新任务

    ABORT(缺省):抛出TaskRejectedException异常,然后不执行DISCARD:不执行,也不抛出异常

    DISCARD_OLDEST:丢弃queue中最旧的那个任务

    CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行

    第二步在类或方法上添加@Async,当调用该方法时,则该方法即是用异常执行的方法单独开个新线程执行。

    1. @Async(“可以指定执行器id,也可以不指定”)  
    2.     public static void testAsyncVoid (){  
    3.         try {  
    4.             //让程序暂停100秒,相当于执行一个很耗时的任务  
    5.     System.out.println(“异常执行打印字符串”);  
    6.             Thread.sleep(100000);  
    7.         } catch (InterruptedException e) {  
    8.             e.printStackTrace();  
    9.         }  
    10.     }  
    @Async(“可以指定执行器id,也可以不指定”)
        public static void testAsyncVoid (){
            try {
                //让程序暂停100秒,相当于执行一个很耗时的任务
        System.out.println(“异常执行打印字符串”);
                Thread.sleep(100000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    

    当在外部调用testAsync方法时即在新线程中执行,由上面<task: annotation-driven/>执行器去维护线程。

    总结:先用context:component-scan去扫描注解,让spring能识别到@Async注解,然后task:annotation-driven去驱动@Async注解,并可以指定默认的线程执行器executor。那么当用@Async注解的方法或类得到调用时,线程执行器会创建新的线程去执行。

     

    上面方法是无返回值的情况,还有异常方法有返回值的例子。

    1. @Async  
    2. public Future<String> testAsyncReturn () {    
    3.     System.out.println(“Execute method asynchronously - ”    
    4.       + Thread.currentThread().getName());    
    5.     try {    
    6.         Thread.sleep(5000);    
    7.         return new AsyncResult<String>(“hello world !!!!”);    
    8.     } catch (InterruptedException e) {    
    9.         //    
    10.     }    
    11.     return null;    
    12. }  
    @Async
    public Future<String> testAsyncReturn () {  
        System.out.println("Execute method asynchronously - "  
          + Thread.currentThread().getName());  
        try {  
            Thread.sleep(5000);  
            return new AsyncResult<String>("hello world !!!!");  
        } catch (InterruptedException e) {  
            //  
        }  
        return null;  
    }
    

    返回的数据类型为Future类型,接口实现类是AsyncResult.

    调用方法如下:

    1. public void test(){  
    2.     Future<String> future = cc.testAsyncReturn();    
    3.     while (true) {  ///这里使用了循环判断,等待获取结果信息    
    4.         if (future.isDone()) {  //判断是否执行完毕    
    5.             System.out.println(“Result from asynchronous process - ” + future.get());    
    6.             break;    
    7.         }    
    8.         System.out.println(“Continue doing something else. ”);    
    9.         Thread.sleep(1000);    
    10.     }    
    11. }  
    public void test(){
        Future<String> future = cc.testAsyncReturn();  
        while (true) {  ///这里使用了循环判断,等待获取结果信息  
            if (future.isDone()) {  //判断是否执行完毕  
                System.out.println("Result from asynchronous process - " + future.get());  
                break;  
            }  
            System.out.println("Continue doing something else. ");  
            Thread.sleep(1000);  
        }  
    }
    

    通过不停的检查Future的状态来获取当前的异步方法是否执行完毕

    参考文章

    编程的方式使用@Async:

    1. @Configuration    
    2. @EnableAsync    
    3. public class SpringConfig {    
    4.       
    5.     private int corePoolSize = 10;    
    6.     private int maxPoolSize = 200;   
    7.     private int queueCapacity = 10;    
    8.     private String ThreadNamePrefix = “MyLogExecutor-“;    
    9.     
    10.     @Bean    
    11.     public Executor logExecutor() {    
    12.         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();    
    13.         executor.setCorePoolSize(corePoolSize);    
    14.         executor.setMaxPoolSize(maxPoolSize);    
    15.         executor.setQueueCapacity(queueCapacity);    
    16.         executor.setThreadNamePrefix(ThreadNamePrefix);    
    17.         // rejection-policy:当pool已经达到max size的时候,如何处理新任务    
    18.         // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行    
    19.         executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());    
    20.         executor.initialize();    
    21.         return executor;    
    22.     }  
    23. }  
    @Configuration  
    @EnableAsync  
    public class SpringConfig {  
    
        private int corePoolSize = 10;  
        private int maxPoolSize = 200; 
        private int queueCapacity = 10;  
        private String ThreadNamePrefix = "MyLogExecutor-";  
    
        @Bean  
        public Executor logExecutor() {  
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();  
            executor.setCorePoolSize(corePoolSize);  
            executor.setMaxPoolSize(maxPoolSize);  
            executor.setQueueCapacity(queueCapacity);  
            executor.setThreadNamePrefix(ThreadNamePrefix);  
            // rejection-policy:当pool已经达到max size的时候,如何处理新任务  
            // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行  
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());  
            executor.initialize();  
            return executor;  
        }
    }
    



    10.@Named

    @Named和Spring的@Component功能相同。@Named可以有值,如果没有值生成的Bean名称默认和类名相同。比如

    @Named public class Person 

    @Named(“cc”) public class Person

     


    11. @Inject

    使用@Inject需要引用javax.inject.jar,它与Spring没有关系,是jsr330规范。

    与@Autowired有互换性。

     


    12. @Singleton

    只要在类上加上这个注解,就可以实现一个单例类,不需要自己手动编写单例实现类。

     


    13.@Valid,@Valided

    @Valid

       网上一大片使用@Valid失效不能用的情况。为什么呢?

    1.@Valid必需使用在以@RequestBody接收参数的情况下。

    2.使用ajax以POST方式提示数据,禁止用Fiddler以及浏览器直接访问的方式测试接口

    3.<mvc:annotation-driven />添加注解驱动。

    4.@Valid是应用在javabean上的校验。

    5.
    1. <dependency>  
    2.             <groupId>org.hibernate</groupId>  
    3.             <artifactId>hibernate-validator</artifactId>  
    4.             <version>4.2.0.Final</version>  
    5.         </dependency>   
    6. <dependency>  
    7.             <groupId>com.fasterxml.jackson.core</groupId>  
    8.             <artifactId>jackson-annotations</artifactId>  
    9.             <version>2.5.3</version>  
    10.         </dependency>  
    11.         <dependency>  
    12.             <groupId>com.fasterxml.jackson.core</groupId>  
    13.             <artifactId>jackson-core</artifactId>  
    14.             <version>2.5.3</version>  
    15.         </dependency>  
    16.         <dependency>  
    17.             <groupId>com.fasterxml.jackson.core</groupId>  
    18.             <artifactId>jackson-databind</artifactId>  
    19.             <version>2.5.3</version>  
    20.         </dependency>  
    21.         <dependency>  
    22.             <groupId>org.codehaus.jackson</groupId>  
    23.             <artifactId>jackson-mapper-asl</artifactId>  
    24.             <version>1.9.8</version>  
    25.         </dependency>  
    26.         <dependency>  
    27.             <groupId>com.fasterxml.jackson.module</groupId>  
    28.             <artifactId>jackson-module-jaxb-annotations</artifactId>  
    29.             <version>2.5.3</version>  
    <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>4.2.0.Final</version>
            </dependency> 
    <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-annotations</artifactId>
                <version>2.5.3</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>2.5.3</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.5.3</version>
            </dependency>
            <dependency>
                <groupId>org.codehaus.jackson</groupId>
                <artifactId>jackson-mapper-asl</artifactId>
                <version>1.9.8</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.module</groupId>
                <artifactId>jackson-module-jaxb-annotations</artifactId>
                <version>2.5.3</version>
    

    这些jar包是需要的。@Valid是使用hibernate validation的时候使用,可参数下面介绍的@RequestBody

    6.@Valid下后面紧跟BindingResult result,验证结果保存在result

     

    例如:

    1. @RequestMapping(“/test”)  
    2.     public String testValid(@Valid User user, BindingResult result){  
    3.         if (result.hasErrors()){  
    4.             List<ObjectError> errorList = result.getAllErrors();  
    5.             for(ObjectError error : errorList){  
    6.                 System.out.println(error.getDefaultMessage());  
    7.             }  
    8.         }    
    9.         return “test”;  
    10. }  
    @RequestMapping("/test")
        public String testValid(@Valid User user, BindingResult result){
            if (result.hasErrors()){
                List<ObjectError> errorList = result.getAllErrors();
                for(ObjectError error : errorList){
                    System.out.println(error.getDefaultMessage());
                }
            }  
            return "test";
    }
    

    在入参User上添加了@Valid做校验,在User类里属性上实行实际的特定校验。

    例如在User的name属性上加

    @NotBlank

    private String name;

     

    全部参数校验如下:

    空检查

    @Null       验证对象是否为null

    @NotNull    验证对象是否不为null, 无法查检长度为0的字符串

    @NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.

    @NotEmpty 检查约束元素是否为NULL或者是EMPTY.

     

    Booelan检查

    @AssertTrue     验证 Boolean 对象是否为 true 

    @AssertFalse    验证 Boolean 对象是否为 false 

     

    长度检查

    @Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内 

    @Length(min=, max=)验证注解的元素值长度在min和max区间内

    日期检查

    @Past           验证 Date 和 Calendar 对象是否在当前时间之前 

    @Future     验证 Date 和 Calendar 对象是否在当前时间之后 

    @Pattern    验证 String 对象是否符合正则表达式的规则

     

    数值检查,建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为”“,Integer为null

    @Min(value=””)            验证 Number 和 String 对象是否大等于指定的值 

    @Max(value=””)             验证 Number 和 String 对象是否小等于指定的值 

    @DecimalMax(value=值) 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度

    @DecimalMin(value=值) 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度

    @Digits     验证 Number 和 String 的构成是否合法 

    @Digits(integer=,fraction=)验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。

     

    @Range(min=, max=) 检查数字是否介于min和max之间.

    @Range(min=10000,max=50000,message=”range.bean.wage”)

    private BigDecimal wage;

     

    @Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)

    @CreditCardNumber信用卡验证

    @Email  验证是否是邮件地址,如果为null,不进行验证,算通过验证。

    @ScriptAssert(lang=,script=, alias=)

    @URL(protocol=,host=,port=,regexp=, flags=)

     

    @Validated

    @Valid是对javabean的校验,如果想对使用@RequestParam方式接收参数方式校验使用@Validated

    使用@Validated的步骤:

    第一步:定义全局异常,让该全局异常处理器能处理所以验证失败的情况,并返回给前台失败提示数据。如下,该类不用在任何xml里配置。

    1. import javax.validation.ValidationException;  
    2.   
    3. import org.springframework.context.annotation.Bean;  
    4. import org.springframework.http.HttpStatus;  
    5. import org.springframework.stereotype.Component;  
    6. import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;  
    7. import org.springframework.web.bind.annotation.ControllerAdvice;  
    8. import org.springframework.web.bind.annotation.ExceptionHandler;  
    9. import org.springframework.web.bind.annotation.ResponseBody;  
    10. import org.springframework.web.bind.annotation.ResponseStatus;  
    11.   
    12. @ControllerAdvice  
    13. @Component  
    14. public class GlobalExceptionHandler {  
    15.     @Bean  
    16.     public MethodValidationPostProcessor methodValidationPostProcessor() {  
    17.         return new MethodValidationPostProcessor();  
    18.     }  
    19.   
    20.     @ExceptionHandler  
    21.     @ResponseBody  
    22.     @ResponseStatus(HttpStatus.BAD_REQUEST)  
    23.     public String handle(ValidationException exception) {  
    24.         System.out.println(“bad request, ” + exception.getMessage());  
    25.         return “bad request, ” + exception.getMessage();  
    26.     }  
    27. }  
    import javax.validation.ValidationException;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.http.HttpStatus;
    import org.springframework.stereotype.Component;
    import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.ResponseStatus;
    
    @ControllerAdvice
    @Component
    public class GlobalExceptionHandler {
        @Bean
        public MethodValidationPostProcessor methodValidationPostProcessor() {
            return new MethodValidationPostProcessor();
        }
    
        @ExceptionHandler
        @ResponseBody
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        public String handle(ValidationException exception) {
            System.out.println("bad request, " + exception.getMessage());
            return "bad request, " + exception.getMessage();
        }
    }
    

    第二步。在XXController.java头上添加@Validated,然后在@RequestParam后台使用上面介绍的验证注解,比如@NotBlank,@Rank.

    如下:

    1. @Controller  
    2. @RequestMapping(“/test”)  
    3. @Validated  
    4. public class TestController extends BaseController {  
    5.   
    6.     @RequestMapping(value = “testValidated”method = RequestMethod.GET)  
    7.     @ResponseBody  
    8.     @ResponseStatus(HttpStatus.BAD_REQUEST)  
    9.     public Object testValidated(@RequestParam(value = “pk”required = true) @Size(min = 1max = 3) String pk,  
    10.             @RequestParam(value = “age”required = false) @Range(min = 1max = 3) String age) {  
    11.         try {  
    12.             return “pk:” + pk + ”,age=” + age;  
    13.         } catch (Throwable t) {  
    14.               
    15.             return buildFailure(“消息列表查询失败”);  
    16.         }  
    17.     }  
    18. }   
    @Controller
    @RequestMapping("/test")
    @Validated
    public class TestController extends BaseController {
    
        @RequestMapping(value = "testValidated", method = RequestMethod.GET)
        @ResponseBody
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        public Object testValidated(@RequestParam(value = "pk", required = true) @Size(min = 1, max = 3) String pk,
                @RequestParam(value = "age", required = false) @Range(min = 1, max = 3) String age) {
            try {
                return "pk:" + pk + ",age=" + age;
            } catch (Throwable t) {
    
                return buildFailure("消息列表查询失败");
            }
        }
    } 
    

    当入非法参数是,会被全局处理器拦截到,(Spring切面编程方式),如果参数非法即刻给前台返回错误数据。

    测试:http://127.0.0.1:8080/TestValidate/test/testValidated?pk=2&age=12

    返回:


    注意

    @Valid是使用hibernateValidation.jar做校验

    @Validated是只用springValidator校验机制使用

    gitHub下载地址


    @Validated与@RequestBody结合使用时,在接口方法里要增加@Valid。例如:

    1. public Object edit(@Valid @RequestBody AddrRo addrRo) {…..}  
    public Object edit(@Valid @RequestBody AddrRo addrRo) {.....}


    14.@RequestBody

    @RequestBody(required=true)

    :有个默认属性required,默认是true,当body里没内容时抛异常。

    application/x-www-form-urlencoded:窗体数据被编码为名称/值对。这是标准的编码格式。这是默认的方式
    multipart/form-data:窗体数据被编码为一条消息,页上的每个控件对应消息中的一个部分。二进制数据传输方式,主要用于上传文件

    注意:必需使用POST方式提交参数,需要使用ajax方式请求,用Fiddler去模拟post请求不能。

    引用jar包:

    Spring相关jar包。

    以及

    1. <dependency>  
    2.             <groupId>com.fasterxml.jackson.core</groupId>  
    3.             <artifactId>jackson-annotations</artifactId>  
    4.             <version>2.5.3</version>  
    5.         </dependency>  
    6.         <dependency>  
    7.             <groupId>com.fasterxml.jackson.core</groupId>  
    8.             <artifactId>jackson-core</artifactId>  
    9.             <version>2.5.3</version>  
    10.         </dependency>  
    11.         <dependency>  
    12.             <groupId>com.fasterxml.jackson.core</groupId>  
    13.             <artifactId>jackson-databind</artifactId>  
    14.             <version>2.5.3</version>  
    15.         </dependency>  
    <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-annotations</artifactId>
                <version>2.5.3</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>2.5.3</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.5.3</version>
            </dependency>
    

    dispatchServlet-mvc.xml配置
    第一种,直接配置MappingJackson2HttpMessageCoverter:

    1. <bean class=“org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping”></bean>  
    2.     <bean class=“org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter”>  
    3.         <property name=“messageConverters”>  
    4.             <bean class=“org.springframework.http.converter.json.MappingJackson2HttpMessageConverter”></bean>  
    5.         </property>  
    6.     </bean>  
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
            <property name="messageConverters">
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
            </property>
        </bean>
    

    第二种:<mvc:annotation-driven/> 就不用配置上面bean,默认会配好。

       Ajax请求:

    1. function  testRequestBody() {  
    2.     var o = {“status”:9};  
    3.      jQuery.ajax({  
    4.             type: “POST”,  
    5.             url: “http://127.0.0.1:8080/TestValidate/test/testValid”,  
    6.             xhrFields:{  
    7.                 withCredentials:true  
    8.             },  
    9.             data: JSON.stringify(o),  
    10.             contentType: “application/json”,  
    11.             dataType: “json”,  
    12.             async: false,  
    13.             success:function (data) {  
    14.                 console.log(data);  
    15.             },  
    16.   
    17.             error: function(res) {  
    18.                  console.log(res);  
    19.             }  
    20.         });  
    21. }  
    function  testRequestBody() {
        var o = {"status":9};
         jQuery.ajax({
                type: "POST",
                url: "http://127.0.0.1:8080/TestValidate/test/testValid",
                xhrFields:{
                    withCredentials:true
                },
                data: JSON.stringify(o),
                contentType: "application/json",
                dataType: "json",
                async: false,
                success:function (data) {
                    console.log(data);
                },
    
                error: function(res) {
                     console.log(res);
                }
            });
    }
    

    后台XXXcontroller.java:

    1. @RequestMapping(value=“/ testValid ”,method=RequestMethod.POST)  
    2. @ResponseBody  
    3. public Object setOrderInfo(@RequestBody InfoVO infoVO,HttpServletRequest request, HttpServletResponse response){  
    4.         InfoVO cVo = getInfoVo(infoVO);  
    5.         return “success”;  
    6.     }  
    @RequestMapping(value="/ testValid ",method=RequestMethod.POST)
    @ResponseBody
    public Object setOrderInfo(@RequestBody InfoVO infoVO,HttpServletRequest request, HttpServletResponse response){
            InfoVO cVo = getInfoVo(infoVO);
            return "success";
        }
    

    开发时,不是报415,就是400错误,头都大了。还是细节没做到位,注意下面几个要点:

    Content-Type必需是application/json

    需要jackson-databind.jar

    <mvc:annotation-driven/>要配置或直接配置bean

    XXXController.jar在post方式接收数据

    最最重要的,使用ajaxpost方式请求。不能用Fiddler模拟,不然会出错。



    15.@CrossOrigin

    是Cross-Origin ResourceSharing(跨域资源共享)的简写

       作用是解决跨域访问的问题,在Spring4.2以上的版本可直接使用。在类上或方法上添加该注解

    例如:

    1. @CrossOrigin  
    2. public class TestController extends BaseController {  
    3.   
    4.     XXXX  
    5.   
    6. }  
    @CrossOrigin
    public class TestController extends BaseController {
    
        XXXX
    
    }
    

    如果失效则可能方法没解决是GET还是POST方式,指定即可解决问题。



    16.@RequestParam

    作用是提取和解析请求中的参数。@RequestParam支持类型转换,类型转换目前支持所有的基本Java类型

    @RequestParam([value=”number”], [required=false])  String number 

    将请求中参数为number映射到方法的number上。required=false表示该参数不是必需的,请求上可带可不带。

     


    17. @PathVariable@RequestHeader@CookieValue@RequestParam, @RequestBody@SessionAttributes, @ModelAttribute;

    @PathVariable处理requet uri部分,当使用@RequestMapping URI template 样式映射时, 即someUrl/{paramId}, 这时的paramId可通过 @Pathvariable注解绑定它传过来的值到方法的参数上

    例如:

    1. @Controller   
    2. @RequestMapping(“/owners/{a}”)   
    3. public class RelativePathUriTemplateController {   
    4.   @RequestMapping(“/pets/{b}”)   
    5.   public void findPet(@PathVariable(“a”) String a,@PathVariable String b, Model model) {       
    6.     // implementation omitted   
    7.   }   
    8. }  
    @Controller 
    @RequestMapping("/owners/{a}") 
    public class RelativePathUriTemplateController { 
      @RequestMapping("/pets/{b}") 
      public void findPet(@PathVariable("a") String a,@PathVariable String b, Model model) {     
        // implementation omitted 
      } 
    }
    

    @RequestHeader@CookieValue: 处理request header部分的注解

    将头部信息绑定到方法参数上:

    1. @RequestMapping(“/test”)   
    2. public void displayHeaderInfo(@RequestHeader(“Accept-Encoding”) String encoding,   
    3.                               @RequestHeader(“Keep-Alive”)long keepAlive)  {   
    4.    
    5.   //…   
    6.    
    7. }  
    @RequestMapping("/test") 
    public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding, 
                                  @RequestHeader("Keep-Alive")long keepAlive)  { 
    
      //... 
    
    }
    

    //将cookie里JSESSIONID绑定到方法参数上

    1. @RequestMapping(“/test”)    
    2. public void displayHeaderInfo(@CookieValue(“JSESSIONID”) String cookie)  {    
    3.     
    4.   //…    
    5.     
    6. }  
    @RequestMapping("/test")  
    public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie)  {  
    
      //...  
    
    }
    

    @RequestParam,  @RequestBody: 处理request body部分的注解,已经介绍过,不用介绍了。

    @SessionAttributes,@ModelAttribute:处理attribute类型是注解。XXXX

     


    18.@Scope

    配置bean的作用域。

    @Controller

    @RequestMapping(“/test”)

    @Scope(“prototype”)

    public class TestController {

     

     

    }

    默认是单例模式,即@Scope(“singleton”),

    singleton:单例,即容器里只有一个实例对象。

    prototype:多对象,每一次请求都会产生一个新的bean实例,Spring不无法对一个prototype bean的整个生命周期负责,容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,由程序员负责销毁该对象,不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,而对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用

    request:对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效

    web.xml增加如下配置:

    1. <listener>  
    2. <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>  
    3.   </listener>  
    4. session:该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效。也要在web.xml配置如下代码:  
    5. <listener>  
    6. <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>  
    7.   </listener>  
    8. global session:作用不大,可不用管他。  
    <listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
      </listener>
    session:该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效。也要在web.xml配置如下代码:
    <listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
      </listener>
    global session:作用不大,可不用管他。
    



    19.@ResponseStatus

    @ResponseStatus用于修饰一个类或者一个方法,修饰一个类的时候,一般修饰的是一个异常类,当处理器的方法被调用时,@ResponseStatus指定的code和reason会被返回给前端。value属性是http状态码,比如404,500等。reason是错误信息

    当修改类或方法时,只要该类得到调用,那么value和reason都会被添加到response里

    例如:

    1. @ResponseStatus(value=HttpStatus.FORBIDDEN, reason=“出现了错误”)  
    2. public class UserException extends RuntimeException{  
    3.   
    4.     XXXXX  
    5. }  
    @ResponseStatus(value=HttpStatus.FORBIDDEN, reason="出现了错误")
    public class UserException extends RuntimeException{
    
        XXXXX
    }
    


    当某处抛出UserException时,则会把value和reason返回给前端。

    1. @RequestMapping(“/testResponseStatus”)  
    2.     public String testResponseStatus(int i){  
    3.         if(i==0)  
    4.             throw new UserNotMatchException();  
    5.         return “hello”;  
    6. }  
    @RequestMapping("/testResponseStatus")
        public String testResponseStatus(int i){
            if(i==0)
                throw new UserNotMatchException();
            return "hello";
    }
    

    修改方法:

    1. @ControllerAdvice  
    2. @Component  
    3. public class GlobalExceptionHandler {  
    4.     @Bean  
    5.     public MethodValidationPostProcessor methodValidationPostProcessor() {  
    6.         return new MethodValidationPostProcessor();  
    7.     }  
    8.   
    9.     @ExceptionHandler  
    10.     @ResponseBody  
    11.     @ResponseStatus(value=HttpStatus.BAD_REQUEST,reason=“哈哈”)  
    12.     public String handle(ValidationException exception) {  
    13.         System.out.println(“bad request, ” + exception.getMessage());  
    14.         return “bad request, ” + exception.getMessage();  
    15.     }  
    16. }  
    @ControllerAdvice
    @Component
    public class GlobalExceptionHandler {
        @Bean
        public MethodValidationPostProcessor methodValidationPostProcessor() {
            return new MethodValidationPostProcessor();
        }
    
        @ExceptionHandler
        @ResponseBody
        @ResponseStatus(value=HttpStatus.BAD_REQUEST,reason="哈哈")
        public String handle(ValidationException exception) {
            System.out.println("bad request, " + exception.getMessage());
            return "bad request, " + exception.getMessage();
        }
    }
    

    结果如下:


    正如上面所说,该方法得到调用,不论是否抛异常,都会把value和reason添加到response里。

    总结:@ResponseStatus是为了在方法或类得到调用时将指定的code和reason添加到response里返前端,就像服务器常给我们报的404错误一样,我们可以自己指定高逼格错误提示。



    20. @RestController

    @RestController = @Controller + @ResponseBody。

    是2个注解的合并效果,即指定了该controller是组件,又指定方法返回的是String或json类型数据,不会解决成jsp页面,注定不够灵活,如果一个Controller即有SpringMVC返回视图的方法,又有返回json数据的方法即使用@RestController太死板。

    灵活的作法是:定义controller的时候,直接使用@Controller,如果需要返回json可以直接在方法中添加@ResponseBody

     

     

    21.@ControllerAdvice

    官方解释是:It is typically used todefine@ExceptionHandler,

     @InitBinder, and@ModelAttribute methods that apply to all@RequestMapping methods

    意思是:即把@ControllerAdvice注解内部使用@ExceptionHandler、@InitBinder、@ModelAttribute注解的方法应用到所有的 @RequestMapping注解的方法。非常简单,不过只有当使用@ExceptionHandler最有用,另外两个用处不大。

    1. @ControllerAdvice    
    2. public class GlobalExceptionHandler {    
    3.     @ExceptionHandler(SQLException.class)    
    4.     @ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR,reason=”sql查询错误”)    
    5.     @ResponseBody    
    6.     public ExceptionResponse handleSQLException(HttpServletRequest request, Exception ex) {    
    7.         String message = ex.getMessage();    
    8.         return ExceptionResponse.create(HttpStatus.INTERNAL_SERVER_ERROR.value(), message);    
    9.     }   
    10. }  
    @ControllerAdvice  
    public class GlobalExceptionHandler {  
        @ExceptionHandler(SQLException.class)  
        @ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR,reason=”sql查询错误”)  
        @ResponseBody  
        public ExceptionResponse handleSQLException(HttpServletRequest request, Exception ex) {  
            String message = ex.getMessage();  
            return ExceptionResponse.create(HttpStatus.INTERNAL_SERVER_ERROR.value(), message);  
        } 
    }

    即表示让Spring捕获到所有抛出的SQLException异常,并交由这个被注解的handleSQLException方法处理,同时使用@ResponseStatus指定了code和reason写到response上,返回给前端。


    22.元注解包括  @Retention @Target @Document @Inherited四种

    元注解是指注解的注解,比如我们看到的ControllerAdvice注解定义如下。

    1. @Target(ElementType.TYPE)  
    2. @Retention(RetentionPolicy.RUNTIME)  
    3. @Documented  
    4. @Component  
    5. public @interface ControllerAdvice {  
    6.     XXX  
    7. }  
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface ControllerAdvice {
        XXX
    }
    

    @Retention: 定义注解的保留策略:

    @Retention(RetentionPolicy.SOURCE)   //注解仅存在于源码中,在class字节码文件中不包含

    @Retention(RetentionPolicy.CLASS)     //默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,

    @Retention(RetentionPolicy.RUNTIME)  //注解会在class字节码文件中存在,在运行时可以通过反射获取到

     

    @Target:定义注解的作用目标:

    @Target(ElementType.TYPE)   //接口、类、枚举、注解

    @Target(ElementType.FIELD) //字段、枚举的常量

    @Target(ElementType.METHOD) //方法

    @Target(ElementType.PARAMETER) //方法参数

    @Target(ElementType.CONSTRUCTOR)  //构造函数

    @Target(ElementType.LOCAL_VARIABLE)//局部变量

    @Target(ElementType.ANNOTATION_TYPE)//注解

    @Target(ElementType.PACKAGE) ///   

     由以上的源码可以知道,他的elementType 可以有多个,一个注解可以为类的,方法的,字段的等等

     

    @Document:说明该注解将被包含在javadoc

     

    @Inherited:说明子类可以继承父类中的该注解

     

    比如@Valid注解定义是




    表示该注解只能用在方法,属性,构造函数及方法参数上。该注意会被编译到class里可通过反射得到。

     


    23.@RequestMapping

    处理映射请求的注解。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。有6个属性。

    1、 value, method:

    value:指定请求的实际地址,指定的地址可以是URI Template 模式;

    method:指定请求的method类型, GET、POST、PUT、DELETE等;

    比如:

    1. @RequestMapping(value = “/testValid”method = RequestMethod.POST)  
    2. @ResponseBody  
    3. public Object testValid(@RequestBody @Valid Test test,BindingResult result, HttpServletRequest request, HttpServletResponse response) {  
    4.     XXX  
    5. }  
    @RequestMapping(value = "/testValid", method = RequestMethod.POST)
    @ResponseBody
    public Object testValid(@RequestBody @Valid Test test,BindingResult result, HttpServletRequest request, HttpServletResponse response) {
        XXX
    }
    

    value的uri值为以下三类:

    A) 可以指定为普通的具体值;如@RequestMapping(value =”/testValid”)

    B)  可以指定为含有某变量的一类值;如@RequestMapping(value=”/{day}”)

    C) 可以指定为含正则表达式的一类值;如@RequestMapping(value=”/{textualPart:[a-z-]+}.{numericPart:[\\d]+}”)  可以匹配../chenyuan122912请求。

     

    2、 consumes,produces:

    consumes: 指定处理请求的提交内容类型(Content-Type),例如@RequestMapping(value = ”/test”, consumes=”application/json”)处理application/json内容类型

    produces:    指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;

     

    3 params、headers:

    params: 指定request中必须包含某些参数值是,才让该方法处理。

    例如:

    1. @RequestMapping(value = “/test”method = RequestMethod.GET, params=“name=chenyuan”)    
    2.   public void findOrd(String name) {        
    3.     // implementation omitted    
    4.   }  
    @RequestMapping(value = "/test", method = RequestMethod.GET, params="name=chenyuan")  
      public void findOrd(String name) {      
        // implementation omitted  
      }
    

    仅处理请求中包含了名为“name”,值为“chenyuan”的请求.

     

    headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。

    1. @RequestMapping(value = “/test”method = RequestMethod.GET, headers=“Referer=www.baidu.com”)    
    2.   public void findOrd(String name) {        
    3.     // implementation omitted    
    4.   }  
    @RequestMapping(value = "/test", method = RequestMethod.GET, headers="Referer=www.baidu.com")  
      public void findOrd(String name) {      
        // implementation omitted  
      }
    

    仅处理request的header中包含了指定“Refer”请求头和对应值为“www.baidu.com”的请求



    另赠spring提供的注解:


    24. @GetMapping和@PostMapping

     @GetMapping(value = “page”)等价于@RequestMapping(value = “page”, method = RequestMethod.GET)

     @PostMapping(value = “page”)等价于@RequestMapping(value = “page”, method = RequestMethod.POST)


    下篇文章会研究自定义注解,自己动手试试注解的魅力。





                </div>
    
    展开全文
  • Spring 中的注解

    千次阅读 2017-08-02 16:24:39
    service 是有用的相当于 xml配置中得bean id = service 也可以不指定 不指定相当于 bean id = ...不加的话,默认别名就是当前类名,但是首字母小写 Spring注解@Component、@Repository、@Service、@Control

    service  是有用的相当于 xml配置中得bean  id = service  也可以不指定 不指定相当于 bean id =  com. service.service 就是这个类的全限定名,表示给当前类命名一个别名,方便注入到其他需要用到的类中;不加的话,默认别名就是当前类名,但是首字母小写 


    Spring注解@Component@Repository@Service@Controller区别

    所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用 @Repository、@Service 和 @Controller 对分层中的类进行注释,而用 @Component 对那些比较中立的类进行注释。 

    在一个稍大的项目中,通常会有上百个组件,如果这些组件采用xml的bean定义来配置,显然会增加配置文件的体积,查找以及维护起来也不太方便。 Spring2.5为我们引入了组件自动扫描机制,他可以在类路径底下寻找标注了@Component,@Service,@Controller,@Repository注解的类,并把这些类纳入进spring容器中管理。它的作用和在xml文件中使用bean节点配置组件时一样的。要使用自动扫描机制,我们需要打开以下配置信息: 
    Java代码 

    1. <?xml version=”1.0” encoding=”UTF-8” ?> <beansxmlns=”http://www.springframework.org/schema/beans”xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”xmlns:context=”http://www.springframework.org/schema/context”xsi:schemaLocation=”http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-2.5.xsd” 
    2. > 
    3.   
    4. <context:component-scan base-package=”com.eric.spring”>   
    5. </beans>   
    6. 其中base-package为需要扫描的包(含所有子包) @Service用于标注业务层组件,@Controller用于标注控制层组件(如struts中的action),@Repository用于标注数据访问组件,即DAO组件,而@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。  

    [html] view plain copy


    1. @Service  
    2. public class VentorServiceImpl implements iVentorService{     
    3. }   
    4.   
    5. Repository  
    6. public class VentorDaoImpl implements iVentorDao {   
    7. }   
    [html] view plain copy


    1. getBean的默认名称是类名(头字母小写),如果想自定义,可以@Service(“aaaaa”)这样来指定,这种bean默认是单例的,  
    [html] view plain copy


    1. 如果想改变,可以使用  
    [html] view plain copy


    1. @Service(“beanName”)  
    [html] view plain copy


    1. @Scope(“prototype”)来改变。可以使用以下方式指定初始化方法和销毁方法(方法名任意):  
    [html] view plain copy


    1. @PostConstruct  
    [html] view plain copy


    1. public void init() {   
    2.  }   
    3.   
    4.  @PreDestroy  
    5.  public void destory() {   
    6.  }   


    注入方式: 

    把DAO实现类注入到service实现类中,把service的接口(注意不要是service的实现类)注入到action中,注 

    入时不要new 这个注入的类,因为spring会自动注入,如果手动再new的话会出现错误,然后属性加上 

    @Autowired后不需要getter()和setter()方法,Spring也会自动注入。至于更具体的内容,等对注入的方式更 

    加熟练后会做个完整的例子上来。 

    注解: 

    在 spring的配置文件里面只需要加上<context:annotation-config/>和<context:component-scanbase-package=”需要实现注入的类所在包”/>,

    可以使用base-package=”*”表示全部的类。   

    < context:component-scan base-package=”com.eric.spring”> 

    其中base-package为需要扫描的包(含所有子包) 

    在接口前面标上@Autowired和@Qualifier注释使得接口可以被容器注入,当接口存在两个实现类的时候必须指定其中一个来注入,

    使用实现类首字母小写的字符串来注入,如: 

        @Autowired      
       
        @Qualifier(“chinese”)       
       
         private Man man;    
    否则可以省略,只写@Autowired  。 

    @Service服务层组件,用于标注业务层组件,表示定义一个bean,自动根据bean的类名实例化一个首写字母为小写的bean,

    例如Chinese实例化为chinese,如果需要自己改名字则:@Service(“你自己改的bean名”)。   

    @Controller用于标注控制层组件(如struts中的action) 

    @Repository持久层组件,用于标注数据访问组件,即DAO组件 

    @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。 


    @Service 
    public class VentorServiceImpl implements iVentorService { 


    @Repository 
    public class VentorDaoImpl implements iVentorDao { 


    getBean 的默认名称是类名(头字母小写),如果想自定义,可以@Service(“aaaaa”) 这样来指定,这种 

    bean默认是单例的,如果想改变,可以使用@Service(“beanName”)@Scope(“prototype”)来改变。 

    可以使用以下方式指定初始化方法和销毁方法(方法名任意): 

    @PostConstruct 

    public void init() { 



    @PreDestroy 

    public void destory() { 

     

     

     

     

    Spring@Autowired注解、@Resource注解的区别

    BY ETHAN ON 2011 06  02  IN JAVA

    Spring不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource@PostConstruct以及@PreDestroy
    @Resource的作用相当于@Autowired,只不过@AutowiredbyType自动注入,而@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分是nametypeSpring@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
    @Resource装配顺序
    1. 如果同时指定了nametype,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
    2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
    3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
    4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

    @Autowired 与@Resource的区别:

     

    1、 @Autowired与@Resource都可以用来装配bean.都可以写在字段上,或写在setter方法上。

    2、 @Autowired默认按类型装配(这个注解是属业spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false),如果我们想使用名称装配可以结合@Qualifier注解进行使用,如下:

    1

    @Autowired() @Qualifier("baseDao")

    2

    private BaseDao baseDao;

    3@Resource(这个注解属于J2EE的),默认安装名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

    1

    @Resource(name="baseDao")

    2

    private BaseDao baseDao;

    推荐使用:@Resource注解在字段上,这样就不用写setter方法了,并且这个注解是属于J2EE的,减少了与spring的耦合。这样代码看起就比较优雅



    展开全文
  • Spring注解大全和应用

    千次阅读 2018-09-02 00:47:35
    @Controller @RestController: @Service @Autowired @RequestMapping @RequestParam @ModelAttribute @Cacheable @CacheEvict @Resource @PostConstruct @PreDestroy @Repository ...
    1. @Controller
    2. @RestController:
    3. @Service
    4. @Autowired
    5. @RequestMapping
    6. @RequestParam
    7. @ModelAttribute
    8. @Cacheable
    9. @CacheEvict
    10. @Resource
    11. @PostConstruct
    12. @PreDestroy
    13. @Repository
    14. @Component
    15. @Scope
    16. @SessionAttributes
    17. @Required
    18. @Qualifier

    @Controller

    标识一个该类是Spring MVC controller处理器,用来创建处理http请求的对象.

    1@Controller
    2public class TestController {
    3        @RequestMapping("/test")
    4        public String test(Map<String,Object> map){
    5
    6            return "hello";
    7        }
    8}

    @RestController

    Spring4之后加入的注解,原来在@Controller中返回json需要@ResponseBody来配合,如果直接用@RestController替代@Controller就不需要再配置@ResponseBody,默认返回json格式。

    1@RestController
    2public class TestController {
    3        @RequestMapping("/test")
    4        public String test(Map<String,Object> map){
    5
    6            return "hello";
    7        }
    8}

    @Service

    用于标注业务层组件,说白了就是加入你有一个用注解的方式把这个类注入到spring配置中

    @Autowired

    用来装配bean,都可以写在字段上,或者方法上。
    默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,例如:@Autowired(required=false)

    @RequestMapping

    类定义处: 提供初步的请求映射信息,相对于 WEB 应用的根目录。
    方法处: 提供进一步的细分映射信息,相对于类定义处的 URL。

    用过RequestMapping的同学都知道,他有非常多的作用,因此详细的用法
    我会在下一篇文章专门讲述,请关注公众号哦,以免错过。

    @RequestParam

    用于将请求参数区数据映射到功能处理方法的参数上
    例如

    1public Resp test(@RequestParam Integer id){
    2        return Resp.success(customerInfoService.fetch(id));
    3    }

    这个id就是要接收从接口传递过来的参数id的值的,如果接口传递过来的参数名和你接收的不一致,也可以如下

    1public Resp test(@RequestParam(value="course_id") Integer id){
    2        return Resp.success(customerInfoService.fetch(id));
    3    }

    其中course_id就是接口传递的参数,id就是映射course_id的参数名

    @ModelAttribute

    使用地方有三种:

    1. 标记在方法上。

    标记在方法上,会在每一个@RequestMapping标注的方法前执行,如果有返回值,则自动将该返回值加入到ModelMap中。

    A.在有返回的方法上:

    当ModelAttribute设置了value,方法返回的值会以这个value为key,以参数接受到的值作为value,存入到Model中,如下面的方法执行之后,最终相当于 model.addAttribute(“user_name”, name);假如 @ModelAttribute没有自定义value,则相当于
    model.addAttribute(“name”, name);

    1@ModelAttribute(value="user_name")
    2    public String before2(@RequestParam(required = false) String name, Model model) {
    3        System.out.println("进入了2:" + name);
    4        return name;
    5    }
    B.在没返回的方法上:

    需要手动model.add方法

    1    @ModelAttribute
    2    public void before(@RequestParam(required = false) Integer age, Model model) {
    3        model.addAttribute("age", age);
    4        System.out.println("进入了1:" + age);
    5    }

    我们在当前类下建一个请求方法:

     1@RequestMapping(value="/mod")
    2    public Resp mod(
    3            @RequestParam(required = false)
     String name,
    4            @RequestParam(required = false) Integer age, 
    5            Model model)
    {
    6        System.out.println("进入mod");
    7        System.out.println("参数接受的数值{name="+name+";age="+age+"}");
    8        System.out.println("model传过来的值:"+model);
    9        return Resp.success("1");
    10    }

    在浏览器中输入访问地址并且加上参数:
    http://localhost:8081/api/test/mod?name=我是小菜&age=12

    最终输出如下:

    1进入了1:40
    2进入了2:我是小菜
    3进入mod
    4参数接受的数值{name=我是小菜;age=12}
    5model传过来的值:{age=40, user_name=我是小菜}

    2. 标记在方法的参数上。

    标记在方法的参数上,会将客户端传递过来的参数按名称注入到指定对象中,并且会将这个对象自动加入ModelMap中,便于View层使用.
    我们在上面的类中加入一个方法如下

     1@RequestMapping(value="/mod2")
    2    public Resp mod2(@ModelAttribute("user_name") String user_name, 
    3            @ModelAttribute("name") String name,
    4            @ModelAttribute("age") Integer age,Model model)
    {
    5        System.out.println("进入mod2");
    6        System.out.println("user_name:"+user_name);
    7        System.out.println("name:"+name);
    8        System.out.println("age:"+age);
    9        System.out.println("model:"+model);
    10        return Resp.success("1");
    11    }

    在浏览器中输入访问地址并且加上参数:
    http://localhost:8081/api/test/mod2?name=我是小菜&age=12
    最终输出:

    1进入了1:40
    2进入了2:我是小菜
    3进入mod2
    4user_name:我是小菜
    5name:我是小菜
    6age:40
    7model:{user_name=我是小菜, org.springframework.validation.BindingResult.user_name=org.springframework.validation.BeanPropertyBindingResult: 0 errors, name=我是小菜, org.springframework.validation.BindingResult.name=org.springframework.validation.BeanPropertyBindingResult: 0 errors, age=40, org.springframework.validation.BindingResult.age=org.springframework.validation.BeanPropertyBindingResult: 0 errors}

    从结果就能看出,用在方法参数中的@ModelAttribute注解,实际上是一种接受参数并且自动放入Model对象中,便于使用。

    @Cacheable

    用来标记缓存查询。可用用于方法或者类中,

    当标记在一个方法上时表示该方法是支持缓存的,
    当标记在一个类上时则表示该类所有的方法都是支持缓存的。

    参数列表

    参数 解释 例子
    value 名称 @Cacheable(value={”c1”,”c2”}
    key key @Cacheable(value=”c1”,key=”#id”)
    condition 条件 @Cacheable(value=”c1”,condition=”#id=1”)

    比如@Cacheable(value=”UserCache”) 标识的是当调用了标记了这个注解的方法时,逻辑默认加上从缓存中获取结果的逻辑,如果缓存中没有数据,则执行用户编写查询逻辑,查询成功之后,同时将结果放入缓存中。
    但凡说到缓存,都是key-value的形式的,因此key就是方法中的参数(id),value就是查询的结果,而命名空间UserCache是在spring*.xml中定义.

    1@Cacheable(value="UserCache")// 使用了一个缓存名叫 accountCache   
    2public Account getUserAge(int id) {  
    3     //这里不用写缓存的逻辑,直接按正常业务逻辑走即可,
    4     //缓存通过切面自动切入  
    5    int age=getUser(id);   
    6     return age;   
    7

    @CacheEvict

    用来标记要清空缓存的方法,当这个方法被调用后,即会清空缓存。@CacheEvict(value=”UserCache”)

    参数列表

    参数 解释 例子
    value 名称 @CachEvict(value={”c1”,”c2”}
    key key @CachEvict(value=”c1”,key=”#id”)
    condition 缓存的条件,可以为空
    allEntries 是否清空所有缓存内容 @CachEvict(value=”c1”,allEntries=true)
    beforeInvocation 是否在方法执行前就清空 @CachEvict(value=”c1”,beforeInvocation=true)

    @Resource

    @Resource的作用相当于@Autowired
    只不过@Autowired按byType自动注入,
    而@Resource默认按 byName自动注入罢了。

    @Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

    @Resource装配顺序:

    1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
    2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
    3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
    4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;

    @PostConstruct

    用来标记是在项目启动的时候执行这个方法。用来修饰一个非静态的void()方法
    也就是spring容器启动时就执行,多用于一些全局配置、数据字典之类的加载

    被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。PreDestroy()方法在destroy()方法执行执行之后执

    @PreDestroy

    被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前

    @Repository

    用于标注数据访问组件,即DAO组件

    @Component

    泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注

    @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是一样的。
     1@Controller
    2@SessionAttributes(value={"names"},types={Integer.class})
    3public class ScopeService {
    4        @RequestMapping("/testSession")
    5        public String test(Map<String,Object> map){
    6            map.put("names", Arrays.asList("a","b","c"));
    7            map.put("age"12);
    8            return "hello";
    9        }
    10}

    @Required

    适用于bean属性setter方法,并表示受影响的bean属性必须在XML配置文件在配置时进行填充。否则,容器会抛出一个BeanInitializationException异常。

    @Qualifier

    当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱

    觉得本文对你有帮助?请分享给更多人

    关注「编程无界」,提升装逼技能

    展开全文
  • Spring系列之Spring常用注解总结

    千次阅读 2019-04-25 16:55:05
    传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事物,这么做有两个缺点: 1、如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么.xml文件又会非常多。...
  • SpringBoot注解最全详解(整合超详细版本)

    万次阅读 多人点赞 2019-09-16 09:11:34
    使用注解的优势: 1.采用纯java代码,不在需要配置繁杂的xml文件 2.在配置中也可享受面向对象带来的好处 3.类型安全对重构可以提供良好的支持 4.减少复杂配置文件的同时亦能享受到springIoC容器提供的功能 ...
  • Spring注解详解

    万次阅读 多人点赞 2012-02-28 19:04:21
    概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作。如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO 的属性名、类型等信息...
  • Spring注解式开发

    千次阅读 2018-07-24 15:25:08
    最近在学习spring注解开发,想和大家分享,spring4以前我们都是编写spring的配置文件进行spring的程序的开发,在Spring4以后引入了全注解模式的开发,去除了编写繁琐的配置文件,使用配置类即可进行bean的扫描和...
  • Spring注解的实现原理

    万次阅读 2017-08-13 19:03:08
    要理解java注解首先要掌握几个概念,第一字节码中的attribute_info区域的作用,第二java反射,第三xml的解析。注解起作用的过程中,注解信息只起着配置信息的作用,注解没有行为,没有动作,就把它看成是存储在...
  • 注解(Annotation)很重要,未来的开发模式都是基于注解的,JPA是基于注解的,Spring2.5以上都是基于注解的,Hibernate3.x以后也是基于注解的,现在的Struts2有一部分也是基于注解的了,注解是一种趋势,现在已经有...
  • spring注解

    千次阅读 2019-04-03 16:54:45
    前段时间面试被面试官问到spring都有哪些注解,一时半会答出几个,感觉好尴尬,于是今天特意把spring里面的注解找出来并且给予说明。整理过程中难免有疏忽,各位如果有不同意见请反馈,部分注解没有找到说明,后期补...
  • Spring 注解

    千次阅读 2019-07-14 22:23:30
    @Configuration 作用:指定当前类是一个配置类 package config; import org.springframework.context.annotation.Configuration; @Configuration public class Spring...作用:用于通过注解指定Spring在创...
  • 【Spring实战】Spring注解配置工作原理源码解析

    万次阅读 多人点赞 2017-07-24 08:27:59
    一、背景知识在【Spring实战】Spring容器...由于上文中大部分都基于注解进行设置的(Spring实战系列篇demo大部分也都是基于注解实现的),因此就想弄明白Spring注解是怎么工作的,这个也是分析上文中实现原理的一个
  • 写在前面 今天,面了一个工作5年的小...问Spring就只知道IOC和AOP的概念,深一点就不知道了!再问项目。。。哎,算了,不说了! 大家对于设计模式、高并发和Java8新特性,不了解的,就去看我的专栏吧!今天,我们来
  • 精进SpringSpring常用注解【经典总结】

    万次阅读 多人点赞 2019-06-11 13:45:03
    Spring的一个核心功能是IOC,就是将Bean初始化加载到容器中,Bean是如何加载到容器的,可以使用Spring注解方式或者Spring XML配置方式。 Spring注解方式减少了配置文件内容,更加便于管理,并且使用注解可以大大...
  • 史上最全的java spring注解,没有之一

    万次阅读 多人点赞 2018-04-12 14:17:44
    注解是个好东西,但好东西我们也...1.@Configuration注解该类等价 与XML中配置beans,相当于Ioc容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean,与xml中配置的bean意思一样。@Configurati...
  • spring注解及扩展

    千次阅读 2018-08-05 21:38:38
    1,spring配置注解 spring建议通过注解配置,替代原xml配置方式。 使用配置类替代xml配置的优势大体: 1,xml配置维护容易出错而且不易检查,java配置类基于java语法检查,对于java程序员更友好,易于维护; 2,...
  • spring注解是如何实现的

    万次阅读 2019-11-04 19:02:09
    用过spring的人都知道,spring简单的通过注解就可以完成很多时间,但这些东西是如何实现的呢以及如何应用到我们自己的代码中?接下来,让我们一起开启注解的旅程。 首先申明本文的重点不是讲解spring注解,也不...
  • Spring注解实现原理

    万次阅读 2018-12-07 09:54:05
    先来说说注解是什么: 注解顾名思义,就是类似于添加注释,但是又不跟注释完全一样,因此,我们可以将它理解为将类或者方法与特定的信息进行关联。 那么注解如何实现? 1、接口使用@interface定义。 2、通过继承...
  • Spring注解Annotation(二)

    千次阅读 2016-06-29 20:59:55
    Spring注解开发需要jar包 和 xml开发 一样的 ! 第一步: 新建项目, 导入jar包 第二步: 在需要spring创建对象类上面 添加@Component (注解 来自spring2.5 )// xml 配置 // @Component("userService")当中 use
1 2 3 4 5 ... 20
收藏数 435,955
精华内容 174,382
关键字:

spring注解