zoukankan      html  css  js  c++  java
  • spring注解

    why(为什么要使用spring注解):

    有助于减少甚至消除配置<property>元素和<constructor-arg>元素,让spring自动识别如何装配bean的依赖关系。

    <?xml version="1.0" encoding="UTF-8"?>
     <beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
       
          <bean id="tiger" class="org.xrq.action.by.Tiger" />
          
          <bean id="zoo" class="org.xrq.action.by.Zoo">
             <property name="animal" ref="tiger" />
       </bean>
             
     </beans>

    <property>标签过多会引发两个问题:

    • 如果一个Bean中要注入的对象过多,比如十几二十个(这是很正常的),那将导致Spring配置文件非常冗长,可读性与维护性差
    • 如果一个Bean中要注入的对象过多,配置麻烦且一不小心就容易出错

    因此,为了解决使用<property>标签注入对象过多的问题,Spring引入自动装配机制,简化开发者配置难度,降低xml文件配置大小。

    使用注解自动装配与在xml中使用autowire属性自动装配并没有太大差别,但是使用注解方式允许更细粒度的自动装配,可以选择性的标注某一个属性来对其应用自动装配。

    spring容器默认禁用注解装配,所以在使用基于注解的自动装配前,我们需要在spring配置中启用它。最简单的启用方式是使用spring的context命名空间配置中的<context:annotation-config>元素

    在beans标签中加入<context:annotation-config/>即是告诉spring我们打算使用基于注解的自动装配。一旦配置完成,我们就可以对代码添加注解,标识spring应该为属性、方法、构造器进行自动装配。

    spring 3支持几种不同的用于自动装配的注解

     1.spring 自带的@Autowired注解,

     2.JSR-330的@Inject注解:是为了统一各种依赖注入框架的编程规范,JCP发布了是最新的规范,称之为JSR-330,其中@Inject是其核心部件,该注解几乎可以完全替换spring的@Autowired,

         可以用来自动装配方法,属性,构造器,基本上等同于@Autowired

     3.JSR-250的@Resource注解

    @Value:spring 3.0引入的,它是一个新的装配注解,可以让我们使用注解装配string类型的值和基本类型的值,如int ,boolean

    @Value("Eruption")

    private String song;

    表明spring为string类型的属性装配了一个string 类型的值

    <content:annotation-config>有助于完全消除spring配置中的<property>和<constructor-arg>元素,但是我们仍然需要使用<bean>元素显式的定义bean.

    但是spring还有另一个技巧,<context:annotation-scan>元素除了完成与<context:annotation-config>一样的工作,还允许spring自动检测bean和定义bean.这就意味着不使用<bean>元素,spring

    应用中的大多数bean都能够实现定义和装配。<context:annotation-scan>元素会扫描指定的包及其所有的子包,并查找出能够自动注册为spring bean的类,那么它又是如何知道哪些类要注册为spring的bean呢?

    默认情况下,<context:annotation-scan>查找使用构造型注解所标注的类,这些特殊的注解如下:

    @Component:通用的构造型注解,标识该类为spring组件

    @Controller:标识将该类定义为spring mvc的controller

    @Repository:标识将该类定义为数据仓库,一般用于持久化层的 DAO component

    @Service:标识将该类定义为服务

    使用@Component标注的任意自定义的注解。

     在项目中,我们可以将所有自动扫描组件都用 @Component 注释,Spring 将会扫描所有用 @Component 注释过得组件。 实际上,@Repository 、 @Service 、 @Controller 三种注释是为了加强代码的阅读性而创造的,可以在不同的应用层中,用不同的注释,我们可以在上一个项目的基础上改一下注释

    package com.springination.springidol
    
    import org.springframework,stereotype.Component;
    
    @Component
    public class Guitar implements Instrument{
        public void play(){
         System.out.println("strum strum strum");
       }
    }

    spring 扫描com.springination.springidol包时,会发现使用@Component 注解所标注的Guitar,并将其自动注册为spring的bean ,bean的id=guitar(无限定类名)

    如果出现@Component("eddie"),则beanid=eddie,而不是无限定类名

    <context:component-scan>也会自动加载使用@Configuration注解所标注的类,@Configuration注解会做为一个标识告诉spring,这个类包含一个或多个spring bean的定义,这此bean的定义是使用@Bean注解所标注的方法

    @Bean
    public Peromer duke(){
     return new Juggler();
    }

    这个简单方法就是Java配置,它等价于我们之前使用xml所配置的<bean>元素,@Bean告知spring这个方法将返回一个对象,该对象应该被注册为spring 上下文中的一个bean,方法名将作为该bean的id,在该方法中所实现的所有逻辑都是为了创建一个bean,即new Juggler()对象出来。

    @Bean
    private Poem sonnet29(){
     return new Sonnet29();
    }
    
    @Bean
    public Performer poeticDuke(){
      return new PoeticJuggler(sonnet29());
    }

    创建一个PoeticJuggler bean,通过构造器为它装配sonnet29 bean.

    注意:在spring的java配置中,通过声明方法引用一个bean并不等同于调用该方法,如果真是这样,每次调用sonnet29(),都将得到该bean 的一个新的实例

    通过使用@Bean注解标注sonnet29()方法,会告知spring 我们希望该方法定义的bean要被注册到spring的应用上下文中,因此,在其他bean的声明方法中引用这个方法时

    spring会拦截该方法的调用,并尝试在应用上下文中查找该Bean,而不是让方法创建一个新的实例。

    带有 @Configuration 的注解类表示这个类可以使用 Spring IoC 容器作为 bean 定义的来源。@Bean 注解告诉 Spring,一个带有 @Bean 的注解方法将返回一个对象,该对象应该被注册为在 Spring 应用程序上下文中的 bean。最简单可行的 @Configuration 类如下所示:

    package com.tutorialspoint;
    import org.springframework.context.annotation.*;
    @Configuration
    public class HelloWorldConfig {
       @Bean 
       public HelloWorld helloWorld(){
          return new HelloWorld();
       }
    }

    上面的代码将等同于下面的 XML 配置:

    <beans>
       <bean id="helloWorld" class="com.tutorialspoint.HelloWorld" />
    </beans>

    example:Instrumentlist 类中有instrument属性,期望自动装配instrument属性

    @Autowired

    private Instrument instrument;//此处需要删除相应的setter方法

    ===》等同于

    @Autowired

    public void setInstrument(Instrument instrument){

          this.instrument = instrument;

    }

    //当spring发现我们对setInstrument方法使用了@Autowired注解时,spring会尝试对该方法执行byType自动装配

      <bean id="instrument" class="com.zf.springidol.Instrument" />

    <bean id="kenny" class="com.zf.springidol.Instrumentlist">

       <property name="animal" ref="instrument" />   //若使用了@Autowired注解其属性instrument后,则这个property就可以删除了

    </bean>

    如果有足够多的bean都完全满足装配条件,并且都可以被装配到属性或参数中,@Autowired注解没有办法选择哪一个bean才是它真正需要的,此时会抛出一个

    NoSuchBeanDefinitionException异常,表示装配失败了。此时可以配合使用@Qualifier注解(此注解是通过指定beanid来缩小装配范围。)

    自动装配就是让Spring自动满足bean依赖的一种方式,在满足依赖的过程中,会在Spring的上下文中寻找匹配一个bean需求的其他bean。为了声明要进行自动装配,我们可以借助Spring的 @Autowried注解。
    比如说CDPlayer类,它在构造器上添加了 @Autowried注解,这表明当创建CDPlayer bean的时候,会通过这个构造器来进行实例化并且会传入一个可设置给CompactDisc类型的bean

    package soundsystem;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class CDPlayer implements MediaPlayer {
      private CompactDisc cd;
    
      @Autowired
      public CDPlayer(CompactDisc cd) {
        this.cd = cd;
      }
    
      public void play() {
        cd.play();
      }
    
    }

    总结一下,自动装配bean的过程:
    一、把需要被扫描的类,添加 @Component注解,使它能够被Spring自动发现。
    二、通过显示的设置Java代码 @ComponentScan注解或XML配置,让Spring开启组件扫描,并将扫描的结果类创建bean。
    三、@Autowried注解能偶实现bean的自动装配,实现依赖注入。

    创建CompactDisc接口:

    package soundsystem;
    
    public interface CompactDisc {
      void play();
    }

    实现CompactDisc接口:

    package soundsystem;
    import org.springframework.stereotype.Component;
    
    @Component
    public class SgtPeppers implements CompactDisc {
    
      private String title = "Sgt. Pepper's Lonely Hearts Club Band";  
      private String artist = "The Beatles";
      
      public void play() {
        System.out.println("Playing " + title + " by " + artist);
      }
     
    }

    在SgtPeppers类上使用了 @Component注解,这个注解表明该类会作为组件类,并告知Spring要为这个类创建bean,不需要显示配置SgtPeppers bean。

     

        @Autowired与@Resource异同:

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

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

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

    它们的作用相同都是用注解方式注入对象,但执行顺序不同。@Autowired先byType,@Resource先byName。

     一个创建自定义注解的例子

    public class AnnotionOperator {
        public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException {
            SayHiEmlement element = new SayHiEmlement(); // 初始化一个实例,用于方法调用
            Method[] methods = SayHiEmlement.class.getDeclaredMethods(); // 获得所有方法
            
            for (Method method : methods) {
                SayHiAnnotation annotationTmp = null;
                if((annotationTmp = method.getAnnotation(SayHiAnnotation.class))!=null) // 检测是否使用了我们的注解
                    method.invoke(element,annotationTmp.paramValue()); // 如果使用了我们的注解,我们就把注解里的"paramValue"参数值作为方法参数来调用方法
                else
                    method.invoke(element, "Rose"); // 如果没有使用我们的注解,我们就需要使用普通的方式来调用方法了
            }
        }

     

  • 相关阅读:
    机器学习——ALS算法
    机器学习——Kmeans算法
    机器学习——欧式距离和余弦距离
    《JAVA策略模式》
    POSTGRESQL 数据库导入导出
    SpringBoot解决前后端全局跨域问题WebMvcConfigurer
    java读取json文件进行解析,String转json对象
    docker: Error response from daemon: Conflict. The container name "/mysql8.0" is already
    学习笔记:shell 中 [-eq] [-ne] [-gt] [-lt] [ge] [le]
    linux 判断一个用户是否存在
  • 原文地址:https://www.cnblogs.com/zf201149/p/9261113.html
Copyright © 2011-2022 走看看