Spring IOC 常用注解

canca canca
2014-02-12 16:44
1
0
注解实现Bean配置主要用来进行如依赖注入、生命周期回调方法定义等,不能消除XML文件中的Bean元数据定义,且基于XML配置中的依赖注入的数据将覆盖基于注解配置中的依赖注入的数据
注册注解处理器

? 方式一:bean

[html] view plain copy
  1. <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>  

? 方式二: 命名空间<context:annotation-config />

<context:annotationconfig /> 将隐式地向Spring 容器注册AutowiredAnnotationBeanPostProcessor 、CommonAnnotationBeanPostProcessor 、 PersistenceAnnotationBeanPostProcessor 以及RequiredAnnotationBeanPostProcessor 这4 个BeanPostProcessor 。

? 方式三: 命名空间<context:component-scan />

如果要使注解工作,则必须配置component-scan ,实际上不需要再配置annotation-config。

[html] view plain copy
  1. <context:component-scan base-package="com.spring.ioc5">  
  2.         <!-- annotation 通过注解来过滤          org.example.SomeAnnotation    
  3.              assignable 通过指定名称过滤        org.example.SomeClass  
  4.              regex      通过正则表达式过滤      org\.example\.Default.*  
  5.              aspectj    通过aspectj表达式过滤  org.example..*Service+  
  6.          -->  
  7.         <context:include-filter type="regex" expression="com.spring.ioc5.*"/>  
  8.         <context:exclude-filter type="annotation" expression="org.springframework.beans.factory.annotation.Autowired"/>  
  9. </context:component-scan>  

 

? Spring 支持以下4 种类型的过滤方式:

     ? 注解 org.example.SomeAnnotation 将所有使用SomeAnnotation 注解的类过滤出来

     ? 类名指定 org.example.SomeClass 过滤指定的类

     ? 正则表达式 com.kedacom.spring.annotation.web..* 通过正则表达式过滤一些类

     ? AspectJ 表达式 org.example..*Service+ 通过AspectJ 表达式过滤一些类


Spring3的基于注解实现Bean依赖注入支持如下三种注解:

  • Spring自带依赖注入注解: Spring自带的一套依赖注入注解;
  • JSR-250注解:Java平台的公共注解,是Java EE 5规范之一,在JDK6中默认包含这些注解,从Spring2.5开始支持。
  • JSR-330注解:Java 依赖注入标准,Java EE 6规范之一,可能在加入到未来JDK版本,从Spring3开始支持;
  • JPA注解:用于注入持久化上下文和尸体管理器。


@Required

         ? 例如 

[java] view plain copy
  1. @required                
  2. public  setName(String name){}  
               @  required 负责检查一个 bean在初始化时其声明的  set 方法是否被执行, 当某个被标注了 @Required 的 Setter 方法没有被调用,则 Spring 在解析的时候会抛出异常,以提醒开发者对相应属性进行设置。 @Required 注解只能标注在 Setter 方法之上。因为依赖注入的本质是检查 Setter 方法是否被调用了,而不是真的去检查属性是否赋值了以及赋了什么样的值。如果将该注解标注在非 setXxxx() 类型的方法则被忽略。



@Autowired 采用byType的方式 


[java] view plain copy
  1. @Autowired  
  2. private ISoftPMService softPMService;  
[java] view plain copy
  1. @Autowired(required=false)  
  2.     构造器、字段、方法  

       @Autowired 根据bean 类型从spring 上线文中进行查找,注册类型必须唯一,否则报异常。与@Resource 的区别在于,@Resource 允许通过bean 名称或bean 类型两种方式进行查找@Autowired(required=false) 表示,如果spring 上下文中没有找到该类型的bean 时, 才会使用new SoftPMServiceImpl();
       @Autowired 标注作用于 Map 类型时,如果 Map 的 key 为 String 类型,则 Spring 会将容器中所有类型符合 Map 的 value 对应的类型的 Bean 增加进来,用 Bean 的 id 或 name 作为 Map 的 key。
       @Autowired 还有一个作用就是,如果将其标注在 BeanFactory 类型、ApplicationContext 类型、ResourceLoader 类型、ApplicationEventPublisher 类型、MessageSource 类型上,那么 Spring 会自动注入这些实现类的实例,不需要额外的操作。


@Qualifier 和@AutoWired联合使用,自动装配的策略就变成byName

  使用@Autowired 时,如果找到多个同一类型的bean,则会抛异常,此时可以使用 @Qualifier("beanName"),明确指定bean的名称进行注入,此时与 @Resource指定name属性作用相同。

[java] view plain copy
  1. @Qualifier(value = "限定标识符")     
  2. 字段、方法、参数    

(1)根据基于XML配置中的<qualifier>标签指定的名字进行注入,使用如下方式指定名称 
[java] view plain copy
  1. <qualifier  type="org.springframework.beans.factory.annotation.Qualifier"  value="限定标识符"/>    
其中type属性可选,指定类型,默认就是Qualifier注解类,name就是给Bean候选者指定限定标识符,一个Bean定义中只允许指定类型不同的<qualifier>,如果有多个相同type后面指定的将覆盖前面的。
[java] view plain copy
  1. @Autowired    
  2.    //根据<qualifier>标签指定Bean限定标识符    
  3.    public void initDataSource(@Qualifier("mysqlDataSource") DataSource dataSource) {    
  4.        this.dataSource = dataSource;    
  5.    }    
使用@Qualifier("mysqlDataSource")来指定候选Bean的限定标识符,我们需要在配置文件中使用<qualifier>标签来指定候选Bean的限定标识符“mysqlDataSource”:
  1. <bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">   
  2.      <qualifier value="mysqlDataSource"/>   
  3. </bean>  

(2)缺省的根据Bean名字注入 :最基本方式,是在Bean上没有指定<qualifier>标签时一种容错机制,即缺省情况下使用Bean标识符注入,但如果你指定了<qualifier>标签将不会发生容错。
  1.     @Autowired  
  2.     @Qualifier(value = "mysqlDataSource2"//指定Bean限定标识符    
  3.     //@Qualifier(value = "mysqlDataSourceBean")   
  4.     //是错误的注入,不会发生回退容错,因为你指定了     
  5.     public void initDataSource(DataSource dataSource) {   
  6.         this.dataSource = dataSource;   
  7.     }   

  8. (3)扩展@Qualifier限定描述符注解: 对@Qualifier的扩展来提供细粒度选择候选者;
    如果我们有两个数据源,分别为Mysql和Oracle,因此注入两者相关资源时就牵扯到数据库相关,如在DAO层注入SessionFactory时,当然可以采用前边介绍的方式,但为了简单和直观我们希望采用自定义注解方式。
    1. 扩展@Qualifier限定描述符注解来分别表示Mysql和Oracle数据源
    1. /** 表示注入Mysql相关 */  
    2. @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})   
    3. @Retention(RetentionPolicy.RUNTIME)   
    4. @Qualifier  
    5. public @interface Mysql {   
    6. }  

    1. /** 表示注入Oracle相关 */  
    2. @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})   
    3. @Retention(RetentionPolicy.RUNTIME)   
    4. @Qualifier  
    5. public @interface Oracle {   
    6. }  

    1. @Autowired  
    2.     public void initDataSource(@Mysql DataSource mysqlDataSource, @Oracle DataSource oracleDataSource) {   
    3.         this.mysqlDataSource = mysqlDataSource;   
    4.         this.oracleDataSource = oracleDataSource;   
    5.     }   

    1. "mysqlDataSourceBean"   class = "org.springframework.jdbc.datasource.DriverManagerDataSource" >   
    2.       "mysqlDataSource" />   
    3.       "cn.javass.spring.chapter12.qualifier.Mysql" />   
    4.   
    5. "oracleDataSource"   class = "org.springframework.jdbc.datasource.DriverManagerDataSource" >   
    6.        "cn.javass.spring.chapter12.qualifier.Oracle" />   

    7.  
    1.  Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean33.getMysqlDataSoruce());  
    2.  Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean33.getOracleDataSoruce());  
    测试通过

    2.扩展参数的注解
    1. package cn.javass.spring.chapter12.qualifier;   
    2. public enum DataBase {   
    3.     ORACLE, MYSQL;   
    4. }  

    1. @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})   
    2. @Retention(RetentionPolicy.RUNTIME)   
    3. @Qualifier  
    4. public @interface DataSourceType {   
    5.     String ip();      //指定ip,用于多数据源情况   
    6.     DataBase database();//指定数据库类型   
    7. }  

    1. @Autowired  
    2.     public void initDataSource(   
    3.             @DataSourceType(ip="localhost", database=DataBase.MYSQL)   
    4.             DataSource mysqlDataSource,   
    5.             @DataSourceType(ip="localhost", database=DataBase.ORACLE)   
    6.             DataSource oracleDataSource) {   
    7.         this.mysqlDataSource = mysqlDataSource;   
    8.         this.oracleDataSource = oracleDataSource;   
    9.     }   

    1. "mysqlDataSourceBean"   class = "org.springframework.jdbc.datasource.DriverManagerDataSource" >   
    2.      "mysqlDataSource" />   
    3.      "cn.javass.spring.chapter12.qualifier.Mysql" />   
    4.      "cn.javass.spring.chapter12.qualifier.DataSourceType" >   
    5.          "ip"  value= "localhost" />   
    6.          "database"  value= "MYSQL" />   
    7.        
    8.   
    9. "oracleDataSource"   class = "org.springframework.jdbc.datasource.DriverManagerDataSource" >   
    10.      "cn.javass.spring.chapter12.qualifier.Oracle" />   
    11.      "cn.javass.spring.chapter12.qualifier.DataSourceType" >   
    12.          "ip"  value= "localhost" />   
    13.          "database"  value= "ORACLE" />   
    14.        
    15.  

    1. Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean34.getMysqlDataSource());   
    2. Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean34.getOracleDataSoruce());   
    测试通过

    3. 自定义注解限定描述符: 完全不使用@Qualifier,而是自己定义一个独立的限定注解;
    1. @Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})   
    2. @Retention(RetentionPolicy.RUNTIME)   
    3. public @interface CustomQualifier {   
    4.     String value();   
    5. }  

    1. @Autowired  
    2.     public TestBean35(@CustomQualifier("oracleDataSource") DataSource dataSource) {   
    3.         this.dataSoruce = dataSource;   
    4.     } 
    在Spring配置文件中注册CustomQualifier自定义注解限定描述符,只有注册了Spring才能识别:
    1. "customAutowireConfigurer"   class = "org.springframework.beans.factory.annotation.CustomAutowireConfigurer" >   
    2.      "customQualifierTypes" >   
    3.            
    4.              cn.javass.spring.chapter12.qualifier.CustomQualifier   
    5.            
    6.       
    7.  



    @Value

    用于注入SpEL表达式,可以放置在字段方法或参数上

    [java] view plain copy
    1. @Value(value = "SpEL表达式")     
    2. 字段、方法、参数  
    1、可以在类字段上使用该注解:
    1. @Value(value = "#{message}")   
    2. private String message;  


    2、可以放置在带@Autowired注解的方法的参数上
    1. @Autowired  
    2. public void initMessage(@Value(value = "#{message}#{message}") String message) {   
    3.     this.message = message;   
    4. }  


    3、还可以放置在带@Autowired注解的构造器的参数上:
    1. @Autowired  
    2. private TestBean43(@Value(value = "#{message}#{message}") String message) {   
    3.     this.message = message;   
    4. }  



    @Lazy
    定义Bean将延迟初始化
    1. @Component("component")   
    2. @Lazy(true)   
    3. public class TestCompoment {   
    4. ……   
    5. } 

    @DependsOn
    定义Bean初始化及销毁时的顺序
    1. @Component("component")   
    2. @DependsOn({"managedBean"})   
    3. public class TestCompoment {   
    4. ……   
    5. }  

    @Scope
    定义Bean作用域,默认单例
    1. @Component("component")   
    2. @Scope("singleton")   
    3. public class TestCompoment {   
    4. ……   

    @Primary
    自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
    1. @Component("component")   
    2. @Primary  
    3. public class TestCompoment {   
    4. ……   

    @Configuration
    注解需要作为配置的类,表示该类将定义Bean配置元数据,
    @Configuration 注解的类本身也是一个Bean,因为@Configuration被@Component注解了,因此@Configuration注解可以指定 value属性值,如“ctxConfig”就是该Bean的名字,如使用“ctx.getBean("ctxConfig")”将返回该Bean。
    [java] view plain copy
    1. "font-size:10px;font-weight: normal;" > @Configuration ( "ctxConfig" )     
    2. public class ApplicationContextConfig {     
    3.     //定义Bean配置元数据     
    4. }    

    @Bean
    注解配置类中的相应方法,则该方法名默认就是Bean名,该方法返回值就是Bean对象,并定义了Spring IoC容器如何实例化、自动装配、初始化Bean逻辑
    [java] view plain copy
    1. "font-weight: normal;" > "font-size:10px;" > @Bean (name={},     
    2.       autowire=Autowire.NO,     
    3.       initMethod="",     
    4.       destroyMethod="")    
    • name:指定Bean的名字,可有多个,第一个作为Id,其他作为别名;
    • autowire:自动装配,默认no表示不自动装配该Bean,另外还有Autowire.BY_NAME表示根据名字自动装配,Autowire.BY_TYPE表示根据类型自动装配;
    • initMethod和destroyMethod:指定Bean的初始化和销毁方法。

    @Import
    类似于基于XML配置中的 ,基于Java的配置方式提供了@Import来组合模块化的配置类

    [java] view plain copy
    1. "font-size:10px;font-weight: normal;" > @Configuration ( "ctxConfig2" )     
    2. @Import({ApplicationContextConfig.class})     
    3. public class ApplicationContextConfig2 {     
    4.     @Bean(name = {"message2"})     
    5.     public String message() {     
    6.         return "hello";     
    7.     }     
    8. }    






    JSR-250注解 @Resource 

    自动装配,默认根据类型装配,如果指定name属性将根据名字装配,可以使用如下方式来指定

    [java] view plain copy
    1. "white-space:pre" >   @Resource(name = "message")     
    2.     "white-space:pre" >   private String message;    
    • @Resource注解应该只用于setter方法注入,不能提供如@Autowired多参数方法注入;
    • @Resource在没有指定name属性的情况下首先将根据setter方法对于的字段名查找资源,如果找不到再根据类型查找;
    • @Resource首先将从JNDI环境中查找资源,如果没找到默认再到Spring容器中查找,因此如果JNDI环境中有和Spring容器同名的资源时需要注意。
    @PostConstruct和PreDestroy:通过注解指定初始化和销毁方法定义;
    类似于通过 标签的init-method和destroy-method属性指定的初始化和销毁方法,但具有更高优先级,即注解方式的初始化和销毁方法将先执行。
    ? @PostConstruct 在方法上加上注解 @PostConstruct  ,这个方法就会在 Bean  初始化之后被 Spring  容器执 (注: Bean  初始化包括,实例化 Bean  ,并装配 Bean  的属性(依赖注入))。
    ? @PreDestroy              在方法上加上注解 @PreDestroy  ,这个方法就会在 Bean  被销毁前被 Spring  容器执行。



    JSR-330注解

    @Inject:等价于默认的@Autowired,只是没有required属性;

    @Named:指定Bean名字,对应于Spring自带@Qualifier中的缺省的根据Bean名字注入情况;

    @Qualifier:只对应于Spring自带@Qualifier中的扩展@Qualifier限定描述符注解,即只能扩展使用,没有value属性。

发表评论