收藏私塾在线
 

欢迎您来到私塾在线网!   

请登录! 

免费注册 


zhang的笔记
状态: 离线
人气:5023377
访问用户量:4221
笔记经验:
总积分:261656
级别:VIP5
搜索本笔记
ta的交流分类
ta的交流主题贴(544)
ta的所有交流贴(1049)
ta的全部笔记
全部笔记(255)
未分类笔记(1)
Java Web(9)
并发实践(1)
课程问题(0)
Java(22)
架构(1)
缓存(5)
JavaEE(0)
JVM(12)
跟我学spring3(68)
Spring Sec……(43)
Spring 3.x……(25)
Spring Sec……(20)
跟开涛学Spring……(17)
深入剖析Spring……(18)
性能调优(10)
前端(2)
Tomcat源码解读(1)
spring sec……(0)
存档
2014-01(7)
2013-12(10)
2012-10(4)
2012-09(2)
2012-08(31)
2012-07(10)
2012-06(5)
2012-05(41)
2012-04(3)
2012-03(41)
2012-02(54)
2011-11(17)
2011-10(30)

2012-02-23 14:35:30
【第十二章】零配置 之 12.2 注解实现Bean依赖注入 ——跟我学spring3
浏览(21395)|评论(0)   交流分类:Java|笔记分类: 跟我学spring3

12.2  注解实现Bean依赖注入

12.2.1  概述

       注解实现Bean配置主要用来进行如依赖注入、生命周期回调方法定义等,不能消除XML文件中的Bean元数据定义,且基于XML配置中的依赖注入的数据将覆盖基于注解配置中的依赖注入的数据

 

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

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

 

这三种类型的注解在Spring3中都支持,类似于注解事务支持,想要使用这些注解需要在Spring容器中开启注解驱动支持,即使用如下配置方式开启:

 

java代码:
<beans xmlns="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-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config/>

</beans>
 
 

   这样就能使用注解驱动依赖注入了,该配置文件位于“resources/ chapter12/dependecyInjectWithAnnotation.xml”。

 

12.2.2  Spring自带依赖注入注解

一、@Required:依赖检查;

对应于基于XML配置中的依赖检查,但XML配置的依赖检查将检查所有setter方法,详见【3.3.4  依赖检查】;

基于@Required的依赖检查表示注解的setter方法必须,即必须通过在XML配置中配置setter注入,如果没有配置在容器启动时会抛出异常从而保证在运行时不会遇到空指针异常,@Required只能放置在setter方法上,且通过XML配置的setter注入,可以使用如下方式来指定:

 

java代码:
@Requried
setter方法

 

1、准备测试Bean

 

java代码:
package cn.javass.spring.chapter12;
public class TestBean {
    private String message;
    @Required
    public void setMessage(String message) {
        this.message = message;
    }
    public String getMessage() {
        return message;
    }
}

 

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:
<bean id="testBean" class="cn.javass.spring.chapter12.TestBean">
<property name="message" ref="message"/>
</bean>
<bean id="message" class="java.lang.String">
    <constructor-arg index="0" value="hello"/>
</bean>

 

3、测试类和测试方法如下:

 

java代码:
package cn.javass.spring.chapter12;
//省略import
public class DependencyInjectWithAnnotationTest {
    private static String configLocation = "classpath:chapter12/dependecyInjectWithAnnotation.xml";
    private static ApplicationContext ctx = new ClassPathXmlApplicationContext("configLocation");
    //1、Spring自带依赖注入注解
     @Test
    public void testRequiredForXmlSetterInject() {
        TestBean testBean = ctx.getBean("testBean", TestBean.class);
        Assert.assertEquals("hello", testBean.getMessage());
    }
}

 

在XML配置文件中必须指定setter注入,否则在Spring容器启动时将抛出如下异常:

 

java代码:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'testBean' defined in class path resource [chapter12/dependecyInjectWithAnnotation.xml]: Initialization of bean failed;
nested exception is org.springframework.beans.factory.BeanInitializationException: Property 'message' is required for bean 'testBean'

 

 

 

 

二、@Autowired:自动装配

自动装配,用于替代基于XML配置的自动装配,详见【3.3.3  自动装配】。

 

基于@Autowired的自动装配,默认是根据类型注入,可以用于构造器、字段、方法注入,使用方式如下:

 

java代码:
@Autowired(required=true)
构造器、字段、方法

 

@Autowired默认是根据参数类型进行自动装配,且必须有一个Bean候选者注入,如果允许出现0个Bean候选者需要设置属性“required=false”,“required”属性含义和@Required一样,只是@Required只适用于基于XML配置的setter注入方式。

 

(1)、构造器注入:通过将@Autowired注解放在构造器上来完成构造器注入,默认构造器参数通过类型自动装配,如下所示:

 

1、准备测试Bean,在构造器上添加@AutoWired注解:

 

java代码:
package cn.javass.spring.chapter12;
import org.springframework.beans.factory.annotation.Autowired;
public class TestBean11 {
    private String message;
    @Autowired //构造器注入
    private TestBean11(String message) {
        this.message = message;
    }
    //省略message的getter和setter
}

 

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:
<bean id="testBean11" class="cn.javass.spring.chapter12.TestBean11"/>

 

3、测试类如下:

 

java代码:
@Test
public void testAutowiredForConstructor() {
    TestBean11 testBean11 = ctx.getBean("testBean11", TestBean11.class);
    Assert.assertEquals("hello", testBean11.getMessage());
}

    在Spring配置文件中没有对“testBean11”进行构造器注入和setter注入配置,而是通过在构造器上添加@ Autowired来完成根据参数类型完成构造器注入。

 

 

 

(2)、字段注入:通过将@Autowired注解放在构造器上来完成字段注入。

 

1、准备测试Bean,在字段上添加@AutoWired注解:

 

java代码:
package cn.javass.spring.chapter12;
import org.springframework.beans.factory.annotation.Autowired;
public class TestBean12 {
    @Autowired //字段注入
    private String message;
    //省略getter和setter
}

 

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:
<bean id="testBean12" class="cn.javass.spring.chapter12.TestBean12"/>

 

3、测试方法如下:

 

java代码:
@Test
public void testAutowiredForField() {
    TestBean12 testBean12 = ctx.getBean("testBean12", TestBean12.class);
    Assert.assertEquals("hello", testBean12.getMessage());
}

    字段注入在基于XML配置中无相应概念,字段注入不支持静态类型字段的注入。

 

 

(3)、方法参数注入:通过将@Autowired注解放在方法上来完成方法参数注入。

 

1、准备测试Bean,在方法上添加@AutoWired注解:

 

java代码:
package cn.javass.spring.chapter12;
import org.springframework.beans.factory.annotation.Autowired;
public class TestBean13 {
    private String message;
    @Autowired //setter方法注入
    public void setMessage(String message) {
        this.message = message;
    }
    public String getMessage() {
        return message;
    }
}

 

 

 

java代码:
package cn.javass.spring.chapter12;
//省略import
public class TestBean14 {
    private String message;
    private List<String> list;
    @Autowired(required = true) //任意一个或多个参数方法注入
    private void initMessage(String message, ArrayList<String> list) {
        this.message = message;
        this.list = list;
    }
    //省略getter和setter
}

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:
<bean id="testBean13" class="cn.javass.spring.chapter12.TestBean13"/>
<bean id="testBean14" class="cn.javass.spring.chapter12.TestBean14"/>
<bean id="list" class="java.util.ArrayList">
    <constructor-arg index="0">
        <list>
            <ref bean="message"/>
            <ref bean="message"/>
        </list>
   </constructor-arg>        
</bean>

 

3、测试方法如下:

 

java代码:
@Test
public void testAutowiredForMethod() {
    TestBean13 testBean13 = ctx.getBean("testBean13", TestBean13.class);
    Assert.assertEquals("hello", testBean13.getMessage());
 
    TestBean14 testBean14 = ctx.getBean("testBean14", TestBean14.class);
    Assert.assertEquals("hello", testBean14.getMessage());
    Assert.assertEquals(ctx.getBean("list", List.class), testBean14.getList());
}
 

 

方法参数注入除了支持setter方法注入,还支持1个或多个参数的普通方法注入,在基于XML配置中不支持1个或多个参数的普通方法注入,方法注入不支持静态类型方法的注入。

 

注意“initMessage(String message, ArrayList<String> list)”方法签名中为什么使用ArrayList而不是List呢?具体参考【3.3.3  自动装配】一节中的集合类型注入区别。

 

 

 

 

 

三、@Value:注入SpEL表达式;

 

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

 

java代码:
@Value(value = "SpEL表达式")
字段、方法、参数

 

1、可以在类字段上使用该注解:

 

java代码:
@Value(value = "#{message}")
private String message;

 

2、可以放置在带@Autowired注解的方法的参数上:

 

java代码:
@Autowired
public void initMessage(@Value(value = "#{message}#{message}") String message) {
    this.message = message;
}

 

3、还可以放置在带@Autowired注解的构造器的参数上:

 

java代码:
@Autowired
private TestBean43(@Value(value = "#{message}#{message}") String message) {
    this.message = message;
}

    具体测试详见DependencyInjectWithAnnotationTest 类的testValueInject测试方法。

 

 

 

 

四、@Qualifier:限定描述符,用于细粒度选择候选者;

 

@Autowired默认是根据类型进行注入的,因此如果有多个类型一样的Bean候选者,则需要限定其中一个候选者,否则将抛出异常,详见【3.3.3  自动装配】中的根据类型进行注入;

 

@Qualifier限定描述符除了能根据名字进行注入,但能进行更细粒度的控制如何选择候选者,具体使用方式如下:

 

java代码:
@Qualifier(value = "限定标识符")
字段、方法、参数

 

(1)、根据基于XML配置中的<qualifier>标签指定的名字进行注入,使用如下方式指定名称:

 

java代码:
<qualifier  type="org.springframework.beans.factory.annotation.Qualifier"  value="限定标识符"/>

 

其中type属性可选,指定类型,默认就是Qualifier注解类,name就是给Bean候选者指定限定标识符,一个Bean定义中只允许指定类型不同的<qualifier>,如果有多个相同type后面指定的将覆盖前面的。

    

         

1、准备测试Bean:

 

java代码:
package cn.javass.spring.chapter12;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class TestBean31 {
    private DataSource dataSource;
    @Autowired
    //根据<qualifier>标签指定Bean限定标识符
    public void initDataSource(@Qualifier("mysqlDataSource") DataSource dataSource) {
        this.dataSource = dataSource;
    }
    public DataSource getDataSource() {
        return dataSource;
    }
}

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:
<bean id="testBean31" class="cn.javass.spring.chapter12.TestBean31"/>

 

我们使用@Qualifier("mysqlDataSource")来指定候选Bean的限定标识符,我们需要在配置文件中使用<qualifier>标签来指定候选Bean的限定标识符“mysqlDataSource”:

 

java代码:
<bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
     <qualifier value="mysqlDataSource"/>
</bean>

 

3、测试方法如下:

 

java代码:
@Test
public void testQualifierInject1() {
    TestBean31 testBean31 = ctx.getBean("testBean31", TestBean31.class);
    try {
        //使用<qualifier>指定的标识符只能被@Qualifier使用
        ctx.getBean("mysqlDataSource");
        Assert.fail();
    } catch (Exception e) {
        //找不到该Bean
        Assert.assertTrue(e instanceof NoSuchBeanDefinitionException);
    }
     Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean31.getDataSource());
}

从测试可以看出使用<qualifier>标签指定的限定标识符只能被@Qualifier使用,不能作为Bean的标识符,如“ctx.getBean("mysqlDataSource")”是获取不到Bean的。

 

 

(2)、缺省的根据Bean名字注入:最基本方式,是在Bean上没有指定<qualifier>标签时一种容错机制,即缺省情况下使用Bean标识符注入,但如果你指定了<qualifier>标签将不会发生容错。

 

1、准备测试Bean:

 

java代码:
package cn.javass.spring.chapter12;
//省略import
public class TestBean32 {
    private DataSource dataSource;
    @Autowired
    @Qualifier(value = "mysqlDataSource2") //指定Bean限定标识符
    //@Qualifier(value = "mysqlDataSourceBean")
    //是错误的注入,不会发生回退容错,因为你指定了<qualifier>
    public void initDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    public DataSource getDataSource() {
        return dataSource;
    }
}
 

 

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:
<bean id="testBean32" class="cn.javass.spring.chapter12.TestBean32"/>
<bean id="oracleDataSource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource"/>

 

3、测试方法如下:

 

java代码:
@Test
public void testQualifierInject2() {
    TestBean32 testBean32 = ctx.getBean("testBean32", TestBean32.class);
    Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean32.getDataSource());
}

 

默认情况下(没指定<qualifier>标签)@Qualifier的value属性将匹配Bean 标识符。

 

 

(3)、扩展@Qualifier限定描述符注解:对@Qualifier的扩展来提供细粒度选择候选者;

 

具体使用方式就是自定义一个注解并使用@Qualifier注解其即可使用。

      

首先让我们考虑这样一个问题,如果我们有两个数据源,分别为Mysql和Oracle,因此注入两者相关资源时就牵扯到数据库相关,如在DAO层注入SessionFactory时,当然可以采用前边介绍的方式,但为了简单和直观我们希望采用自定义注解方式。

 

1、扩展@Qualifier限定描述符注解来分别表示Mysql和Oracle数据源

 

java代码:
package cn.javass.spring.chapter12.qualifier;
import org.springframework.beans.factory.annotation.Qualifier;
/** 表示注入Mysql相关 */
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Mysql {
}

 

 

java代码:
package cn.javass.spring.chapter12.qualifier;
import org.springframework.beans.factory.annotation.Qualifier;
/** 表示注入Oracle相关 */
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Oracle {
}

 

 

2、准备测试Bean:

 

java代码:
package cn.javass.spring.chapter12;
//省略import
public class TestBean33 {
    private DataSource mysqlDataSource;
    private DataSource oracleDataSource;
    @Autowired
    public void initDataSource(@Mysql DataSource mysqlDataSource, @Oracle DataSource oracleDataSource) {
        this.mysqlDataSource = mysqlDataSource;
        this.oracleDataSource = oracleDataSource;
    }
    public DataSource getMysqlDataSource() {
        return mysqlDataSource;
    }
    public DataSource getOracleDataSource() {
        return oracleDataSource;
    }
}

 

 

3、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:
<bean id="testBean33" class="cn.javass.spring.chapter12.TestBean33"/>

 

4、在Spring修改定义的两个数据源:

 

java代码:
<bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
     <qualifier value="mysqlDataSource"/>
     <qualifier type="cn.javass.spring.chapter12.qualifier.Mysql"/>
</bean>
<bean id="oracleDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <qualifier type="cn.javass.spring.chapter12.qualifier.Oracle"/>
</bean>

 

5、测试方法如下:

 

java代码:
@Test
public void testQualifierInject3() {
    TestBean33 testBean33 = ctx.getBean("testBean33", TestBean33.class);
    Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean33.getMysqlDataSoruce());
    Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean33.getOracleDataSoruce());
}

 

测试也通过了,说明我们扩展的@Qualifier限定描述符注解也能很好工作。

 

 

前边演示了不带属性的注解,接下来演示一下带参数的注解:

 

1、首先定义数据库类型:

 

java代码:
package cn.javass.spring.chapter12.qualifier;
public enum DataBase {
    ORACLE, MYSQL;
}

 

2、其次扩展@Qualifier限定描述符注解

 

java代码:
package cn.javass.spring.chapter12.qualifier;
//省略import
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface DataSourceType {
    String ip();      //指定ip,用于多数据源情况
    DataBase database();//指定数据库类型
}

 

3、准备测试Bean:

 

java代码:
package cn.javass.spring.chapter12;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import cn.javass.spring.chapter12.qualifier.DataBase;
import cn.javass.spring.chapter12.qualifier.DataSourceType;
public class TestBean34 {
    private DataSource mysqlDataSource;
    private DataSource oracleDataSource;
    @Autowired
    public void initDataSource(
            @DataSourceType(ip="localhost", database=DataBase.MYSQL)
            DataSource mysqlDataSource,
            @DataSourceType(ip="localhost", database=DataBase.ORACLE)
            DataSource oracleDataSource) {
        this.mysqlDataSource = mysqlDataSource;
        this.oracleDataSource = oracleDataSource;
    }
      //省略getter方法  
}

 

4、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:
<bean id="testBean34" class="cn.javass.spring.chapter12.TestBean34"/>

 

5、在Spring修改定义的两个数据源:

 

java代码:
<bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <qualifier value="mysqlDataSource"/>
    <qualifier type="cn.javass.spring.chapter12.qualifier.Mysql"/>
    <qualifier type="cn.javass.spring.chapter12.qualifier.DataSourceType">
        <attribute key="ip" value="localhost"/>
        <attribute key="database" value="MYSQL"/>
    </qualifier>
</bean>
<bean id="oracleDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <qualifier type="cn.javass.spring.chapter12.qualifier.Oracle"/>
    <qualifier type="cn.javass.spring.chapter12.qualifier.DataSourceType">
        <attribute key="ip" value="localhost"/>
        <attribute key="database" value="ORACLE"/>
    </qualifier>
</bean>

 

6、测试方法如下:

 

java代码:
@Test
public void testQualifierInject3() {
    TestBean34 testBean34 = ctx.getBean("testBean34", TestBean34.class);
    Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean34.getMysqlDataSource());
    Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean34.getOracleDataSoruce());
}

  测试也通过了,说明我们扩展的@Qualifier限定描述符注解也能很好工作。

 

  

 

四、自定义注解限定描述符:完全不使用@Qualifier,而是自己定义一个独立的限定注解;

 

1、首先使用如下方式定义一个自定义注解限定描述符:

 

java代码:
package cn.javass.spring.chapter12.qualifier;
//省略import
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomQualifier {
    String value();
}

 

 

2、准备测试Bean:

 

java代码:
package cn.javass.spring.chapter12;
//省略import
public class TestBean35 {
    private DataSource dataSoruce;
    @Autowired
    public TestBean35(@CustomQualifier("oracleDataSource") DataSource dataSource) {
        this.dataSoruce = dataSource;
    }
    public DataSource getDataSoruce() {
        return dataSoruce;
    }
}

 

3、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:
<bean id="testBean35" class="cn.javass.spring.chapter12.TestBean35"/>

 

4、然后在Spring配置文件中注册CustomQualifier自定义注解限定描述符,只有注册了Spring才能识别:

 

java代码:
<bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
    <property name="customQualifierTypes">
        <set>
            <value>cn.javass.spring.chapter12.qualifier.CustomQualifier</value>
        </set>
   </property>
</bean>

 

5、测试方法如下:

 

java代码:
@Test
public void testQualifierInject5() {
    TestBean35 testBean35 = ctx.getBean("testBean35", TestBean35.class);
    Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean35.getDataSource());
}

    从测试中可看出,自定义的和Spring自带的没什么区别,因此如果没有足够的理由请使用Spring自带的Qualifier注解。

 

    到此限定描述符介绍完毕,在此一定要注意以下几点:

  • 限定标识符和Bean的描述符是不一样的;
  • 多个Bean定义中可以使用相同的限定标识符;
  • 对于集合、数组、字典类型的限定描述符注入,将注入多个具有相同限定标识符的Bean。

 

 

 

 

12.2.3  JSR-250注解

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

 

java代码:
@Resource(name = "标识符")
字段或setter方法

 

1、准备测试Bean:

 

java代码:
package cn.javass.spring.chapter12;
import javax.annotation.Resource;
public class TestBean41 {
    @Resource(name = "message")
    private String message;
    //省略getter和setter
}

 

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:
<bean id="testBean41" class="cn.javass.spring.chapter12.TestBean41"/>

 

3、测试方法如下: 

 

java代码:
@Test
public void testResourceInject1() {
    TestBean41 testBean41 = ctx.getBean("testBean41", TestBean41.class);
    Assert.assertEquals("hello", testBean41.getMessage());
}

    使用非常简单,和@Autowired不同的是可以指定name来根据名字注入。

 

    使用@Resource需要注意以下几点:

  • @Resource注解应该只用于setter方法注入,不能提供如@Autowired多参数方法注入;
  • @Resource在没有指定name属性的情况下首先将根据setter方法对于的字段名查找资源,如果找不到再根据类型查找;
  • @Resource首先将从JNDI环境中查找资源,如果没找到默认再到Spring容器中查找,因此如果JNDI环境中有和Spring容器同名的资源时需要注意。

 

 

二、@PostConstruct和PreDestroy:通过注解指定初始化和销毁方法定义;

 

1、在测试类TestBean41中添加如下代码:

 

java代码:
@PostConstruct
public void init() {
    System.out.println("==========init");
}
@PreDestroy
public void destroy() {
    System.out.println("==========destroy");
}

 

2、修改测试方法如下:

 

java代码:
@Test
public void resourceInjectTest1() {
    ((ClassPathXmlApplicationContext) ctx).registerShutdownHook();
    TestBean41 testBean41 = ctx.getBean("testBean41", TestBean41.class);
    Assert.assertEquals("hello", testBean41.getMessage());
}

    类似于通过<bean>标签的init-method和destroy-method属性指定的初始化和销毁方法,但具有更高优先级,即注解方式的初始化和销毁方法将先执行。

 

 

12.2.4  JSR-330注解

在测试之前需要准备JSR-330注解所需要的jar包,到spring-framework-3.0.5.RELEASE-dependencies.zip中拷贝如下jar包到类路径:

 

com.springsource.javax.inject-1.0.0.jar

 

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

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

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

 

 

1、首先扩展@Qualifier限定描述符注解来表示Mysql数据源

 

java代码:
package cn.javass.spring.chapter12.qualifier;
//省略部分import
import javax.inject.Qualifier;
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface JSR330Mysql {
}
 

 

 

2、准备测试Bean:

 

 

java代码:
package cn.javass.spring.chapter12;
import javax.inject.Inject;
import javax.inject.Named;
import javax.sql.DataSource;
import cn.javass.spring.chapter12.qualifier.JSR330Mysql;
public class TestBean51 {
    private DataSource mysqlDataSource;
    private DataSource oracleDataSource;
    @Inject
    public void initDataSoruce(
            @JSR330Mysql  DataSource mysqlDataSource,
            @Named("oracleDataSource") DataSource oracleDataSource) {
        this.mysqlDataSource = mysqlDataSource;
        this.oracleDataSource = oracleDataSource;

    }
 	//省略getter  
}

 

3、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:
<bean id="testBean51" class="cn.javass.spring.chapter12.TestBean51"/>

 

4、在Spring修改定义的mysqlDataSourceBean数据源:

 

java代码:
<bean id="mysqlDataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
         <qualifier value="mysqlDataSource"/>
         <qualifier type="cn.javass.spring.chapter12.qualifier.Mysql"/>
         <qualifier type="cn.javass.spring.chapter12.qualifier.DataSourceType">
             <attribute key="ip" value="localhost"/>
             <attribute key="database" value="MYSQL"/>
         </qualifier>
         <qualifier type="cn.javass.spring.chapter12.qualifier.JSR330Mysql"/>
</bean>

 

 

5、测试方法如下:

 

java代码:
@Test
public void testInject() {
    TestBean51 testBean51 = ctx.getBean("testBean51", TestBean51.class);
    Assert.assertEquals(ctx.getBean("mysqlDataSourceBean"), testBean51.getMysqlDataSource());
    Assert.assertEquals(ctx.getBean("oracleDataSource"), testBean51.getOracleDataSource());
}

 

 

测试也通过了,说明JSR-330注解也能很好工作。

 

从测试中可以看出JSR-330注解和Spring自带注解依赖注入时主要有以下特点:

  • Spring自带的@Autowired的缺省情况等价于JSR-330的@Inject注解;
  • Spring自带的@Qualifier的缺省的根据Bean名字注入情况等价于JSR-330的@Named注解;
  • Spring自带的@Qualifier的扩展@Qualifier限定描述符注解情况等价于JSR-330的@Qualifier注解。

 

 

 

12.2.5  JPA注解

用于注入EntityManagerFactory和EntityManager。

      

1、准备测试Bean:

 

java代码:
package cn.javass.spring.chapter12;
//省略import
public class TestBean61 {
    @PersistenceContext(unitName = "entityManagerFactory")
    private EntityManager entityManager;
   
    @PersistenceUnit(unitName = "entityManagerFactory")
    private EntityManagerFactory entityManagerFactory;
   
    public EntityManager getEntityManager() {
        return entityManager;
    }
    public EntityManagerFactory getEntityManagerFactory() {
        return entityManagerFactory;
    }
}

 

2、在Spring配置文件(chapter12/dependecyInjectWithAnnotation.xml)添加如下Bean配置:

 

java代码:
<import resource="classpath:chapter7/applicationContext-resources.xml"/>
<import resource="classpath:chapter8/applicationContext-jpa.xml"/>
<bean id="testBean61" class="cn.javass.spring.chapter12.TestBean61"/>

    此处需要引用第七章和八章的配置文件,细节内容请参考七八两章。

 

 

3、测试方法如下:

 

java代码:
@Test
public void testJpaInject() {
    TestBean61 testBean61 = ctx.getBean("testBean61", TestBean61.class);
    Assert.assertNotNull(testBean61.getEntityManager());
    Assert.assertNotNull(testBean61.getEntityManagerFactory());
}

    测试也通过了,说明JPA注解也能很好工作。

 

JPA注解类似于@Resource注解同样是先根据unitName属性去JNDI环境中查找,如果没找到在到Spring容器中查找。

 

 

 

原创内容,转载请注明私塾在线【http://sishuok.com/forum/blogPost/list/0/2545.html

相关笔记推荐
精品视频课程推荐

Java数据结构和算法精讲版
本课程专注于数据结构和算法的内容,使用Java来进行代码示例,不空洞的讲解概念和理论,重点放在代码的实现和示例上。 从零开始、全面系统、成体系的讲解数据结构和基本算法,循序渐进的讲述构建软件系统所常见的数据结构和算法。

Oracle性能优化视频教程
深入浅出地学习Oralce优化的原理与技巧,内容权威全面、细致深入、重点突出,剖析提高挈领,示例丰富充盈,实例和理论完美结合。1:百万级数据量示例;系统高可靠性、高健壮性原理及策略;热表操作;完整性策略;数据库死锁如何解决; 2:索引表空间如何推算规划;b-tree索引的存储结构、索引扫描方式;Oracle执行计划的如何阅读、推荐的索引使用策略; 3:CBO模型;自动化表分析任务、能大幅提高索引性能的原子级表基础约束策略、表分析原理、表间关系和模式; 4:逻辑存储结构、物理存储结构、内存结构、进程结构;ASM存储、逻辑存储结构单元;Oracle实例结构之检查点及实例恢复

高级软件架构师实战培训阶段一
内容概述:本课程专注于构建:高可扩展性、高性能、大数据量、高并发、分布式的系统架构。 从零开始、全面系统、成体系的软件架构课程,循序渐进的讲述构建上述系统架构所需要的各种技术知识和技能。
技术要点: 1:构建基本的业务功能块,基于Maven+Git+Spring mvc+spring+mybatis+ehcache+mysql+X-gen代码生成
 2:高扩展性的分布式体系架构(基于Nginx+Varnish+Memcache+ActiveMQ)
 3:NoSQL的合理使用和架构优化(基于MongoDB)
 4:分布式文件存储和架构优化(基于MogileFS)

深入浅出学Spring Web MVC视频教程
系统、完整的学习Spring Web MVC开发的知识。包括:Spring Web MVC入门;理解DispatcherServlet;注解式控制器开发详解;数据类型转换;数据格式化;数据验证; 拦截器;对Ajax的支持;文件上传下载;表单标签等内容;最后以一个综合的CRUD带翻页的应用示例来综合所学的知识

深入浅出学Spring Data JPA视频教程
系统、完整的学习Spring Data JPA开发的知识。包括:Spring Data JPA入门;JpaRepository基本功能 ;JpaRepository的查询;客户化扩展JpaRepository;Specifications查询。

浏览(21395)|评论(0)   交流分类:Java|笔记分类: 跟我学spring3

评论(0)
请登录后评论 登录

关于我们 | 联系我们 | 用户协议 | 私塾在线服务协议 | 版权声明 | 隐私保护

版权所有 Copyright(C)2009-2012 私塾在线学习网