美文网首页
Spring常用注解

Spring常用注解

作者: 超天大圣JR | 来源:发表于2019-12-18 10:25 被阅读0次

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

    1.声明bean的注解(将普通类加入容器形成Bean)
    • @Component 组件,没有明确的角色
    • @Service 在业务逻辑层使用(业务逻辑层)
    • @Repository 在数据访问层使用(数据访问层)
    • @Controller 在展现层使用,控制器的声明(页面访问控制层)

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

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface Controller {
        String value() default "";
    }
    

    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.*"/>
    
    2.注入bean的注解(从容器中获取Bean即装配bean)

    开发中最常用到的用于装配的注解是:@Autowired和@Resource

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

    @Autowired注解可用于为类的属性、构造器、方法进行注值。默认情况下,其依赖的对象必须存在(bean可用),如果需要改变这种默认方式,可以设置其required属性为false。另外一个比较重要的点就是,@Autowired注解默认按照类型装配,如果容器中包含多个同一类型的Bean,那么启动容器时会报找不到指定类型bean的异常,解决办法是结合@Qualified注解进行限定,指定注入的bean名称,例如:

    public class MovieRecommender {
    
      @Autowired
      private MovieCatalog movieCatalog;
    
      private CustomerPreferenceDao customerPreferenceDao;
    
      @Autowired
      public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
          this.customerPreferenceDao = customerPreferenceDao;
      }
    }
    
    @Controller
    public class HappyController {
        @Autowired //默认依赖的ClubDao 对象(Bean)必须存在
        //@Autowired(required = false) 改变默认方式
        @Qualifier("goodClubService")
        private ClubService clubService;
        
        // Control the people entering the Club
        // do something
    }
    
    @Service(value="goodClubService")
    //使用@Service注解不加value ,默认名称是clubService
    public class ClubServiceImpl implements ClubService {
        @Autowired
        private ClubDao clubDao;
      
        public void doHappy(){
            //do some Happy
        }
     }
    
    • @Resource注解
      @Resource源码:
    @Target({TYPE, FIELD, METHOD})
    @Retention(RUNTIME)
    public @interface Resource {
     String name() default "";
     Class type() default java.lang.Object.class;
    

    对于@Resource注解,它并不属于spring的注解,而是来自于JSR-250。其默认情况下按照bean的名称进行注入,当找不到匹配项时会按照类型装配。当按照名称进行装配时,可以指定其name属性,倘若没有指定,注解标注在哪个字段上,其默认名称就是那个字段的名称。当然,@Resource注解也支持按指定类型进行装配,给它的type属性赋特定类型的值即可(注意,当指定了name属性后,只能按照名称装配)

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

    相同点:

    @Resource的作用相当于@Autowired,均可标注在字段或属性的setter方法上。

    不同点:

    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的异常,解决办法是结合@Qualifier注解进行限定,指定注入的bean名称。
    @Resource有两个中重要的属性:name和type。name属性指定byName,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。
    需要注意的是,@Resource如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时, @Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了。

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

    3. Java配置类相关注解
    • @Configuration 声明当前类为配置类,其中内部组合了@Component注解,表明这个类是一个bean相当于xml形式的Spring配置(类上)
      Spring的官方团队说@Component可以替代 @Configuration注解,事实上我们看源码也可以发现看到,如下
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component  //看这里!!!
    public @interface Configuration {
        String value() default "";
    
    • @Bean 注解在方法上,声明当前方法的返回值为一个bean,替代xml中的方式(方法上)
    • @ComponentScan 用于对Component进行扫描,相当于xml中的context:component-scan/(类上)
    • @WishlyConfiguration 为@Configuration与@ComponentScan的组合注解,可以替代这两个注解
    4.Spring @Configuration与@Component的区别

    代码如下:

    @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获得指向singleton的链接SimpleBean。但是不幸的是,它在签名环境中不起作用

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

    这种现象的原因可以解释如下:

    如果使用@Configuration,则所有标记为的方法@Bean都将被包装到CGLIB包装器中,该包装器将像第一次调用此方法一样工作,然后将执行原始方法的主体,并将结果对象注册在spring上下文中。所有其他调用仅返回从上下文中检索到的bean。

    在上面的第二个代码块中,new 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);
        }
    }
    
    • 原因总结

    使用@ configuration,所有标记为@ bean的方法将被包装成一个CGLIB包装器,它的工作方式就好像是这个方法的第一个调用,那么原始方法的主体将被执行,最终的对象将在spring上下文中注册。所有进一步的调用只返回从上下文检索的bean。

    Spring注解——使用@ComponentScan自动扫描组件

    5.切面(AOP)相关注解

    Spring支持AspectJ的注解式切面编程。

    • @EnableAspectJAutoProxy 开启基于注解的aop模式
    • @Aspect 声明一个切面(类上)
    • @After 在方法执行之后执行(方法上)
    • @Before 在方法执行之前执行(方法上)
    • @Around 在方法执行之前与之后执行(方法上)
    • @PointCut 声明切点
    • @EnableAspectJAutoProxy在java配置类中使用该注解开启Spring对AspectJ代理的支持(类上)
    6.@Bean的属性支持
    • @Scope 设置Spring容器如何新建Bean实例(方法上,必须有@Bean)
      其设置类型包括:

    Singleton (单例,一个Spring容器中只有一个bean实例,默认模式),
    Protetype (每次调用新建一个bean),
    Request (web项目中,给每个http request新建一个bean),
    Session (web项目中,给每个http session新建一个bean),
    GlobalSession(给每一个 global http session新建一个Bean实例)

    • @StepScope 在Spring Batch中还有涉及
    • @Qualifier注解定义Bean名称(方法上,必须有@Bean)。
      当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱。
    • @PostConstruct 用来标记是在项目启动的时候执行这个方法。用来修饰一个非静态的void()方法
      也就是spring容器启动时就执行,多用于一些全局配置、数据字典之类的加载。
      被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。PreDestroy()方法在destroy()方法执行执行之后执
    • @PreDestory 被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前
    7.@Value注解

    @Value 为属性注入值(属性上)
    示例:

    注入普通字符:
    @Value("Michael Jackson")
    String name;
    
    注入操作系统属性:
    @Value("#{systemProperties['os.name']}")
    String osName;
    
    注入表达式结果:
    @Value("#{ T(java.lang.Math).random() * 100 }")
    String randomNumber;
    
    注入其它bean属性:
    @Value("#{domeClass.name}")
    String name;
    
    注入文件资源:
    @Value("classpath:com/hgs/hello/test.txt")
    String Resource file;
    
    注入网站资源:
    @Value("http://www.cznovel.com")
    Resource url;
    
    注入配置文件:
    @Value("${book.name}")
    String bookName;
    
    注入配置使用方法:
    ① 编写配置文件(test.properties)
    book.name=《三体》
    ② @PropertySource 加载配置文件(类上)
    @PropertySource("classpath:com/hgs/hello/test/test.propertie")
    ③ 还需配置一个PropertySourcesPlaceholderConfigurer的bean。
    

    相关文章

      网友评论

          本文标题:Spring常用注解

          本文链接:https://www.haomeiwen.com/subject/unrcnctx.html