零配置 之 Spring 注解实现Bean依赖注入

转载自  【第十二章】零配置 之 12.2 注解实现Bean依赖注入 ——跟我学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容器中开启注解驱动支持,即使用如下配置方式开启:

<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注入,可以使用如下方式来指定:

@Requried  

setter方法  

 

1、准备测试Bean

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配置:

<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、测试类和测试方法如下:

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容器启动时将抛出如下异常:

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的自动装配,默认是根据类型注入,可以用于构造器、字段、方法注入,使用方式如下:

@Autowired(required=true)  

构造器、字段、方法  

 

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

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

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

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配置:

<bean id="testBean11" class="cn.javass.spring.chapter12.TestBean11"/>  

3、测试类如下:

@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注解:

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配置:

<bean id="testBean12" class="cn.javass.spring.chapter12.TestBean12"/>  

3、测试方法如下:

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

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

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

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

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;  }  
}  
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配置:

<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、测试方法如下:

@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表达式,可以放置在字段方法或参数上,使用方式如下:

@Value(value = "SpEL表达式")  

字段、方法、参数  

 

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

@Value(value = "#{message}")  

private String message;  

 

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

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

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

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

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

 

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

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

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

@Qualifier(value = "限定标识符")  

字段、方法、参数  

 

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

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

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

1、准备测试Bean:

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配置:

<bean id="testBean31" class="cn.javass.spring.chapter12.TestBean31"/>  

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

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

 

3、测试方法如下:

@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:

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配置:

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

 

3、测试方法如下:

@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数据源

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 {  
}  
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:

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配置:

<bean id="testBean33" class="cn.javass.spring.chapter12.TestBean33"/>  

 

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

<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、测试方法如下:

@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、首先定义数据库类型:

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

 

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

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:

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配置:

<bean id="testBean34" class="cn.javass.spring.chapter12.TestBean34"/>  

 

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

<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、测试方法如下:

@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、首先使用如下方式定义一个自定义注解限定描述符:

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

 

2、准备测试Bean:

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配置:

<bean id="testBean35" class="cn.javass.spring.chapter12.TestBean35"/>  

 

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

<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、测试方法如下:

@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属性将根据名字装配,可以使用如下方式来指定:

@Resource(name = "标识符")  

字段或setter方法  

 

1、准备测试Bean:

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配置:

<bean id="testBean41" class="cn.javass.spring.chapter12.TestBean41"/>  

 

3、测试方法如下: 

@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中添加如下代码:

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

 

2、修改测试方法如下:

@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数据源

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:

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配置:

<bean id="testBean51" class="cn.javass.spring.chapter12.TestBean51"/>  

 

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

<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、测试方法如下:

@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:

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配置:

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

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

3、测试方法如下:

@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://www.mzph.cn/news/326646.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CLR运行时细节 - 继承多态的实现

关于多态不多解释了,在运行时决定和调用具体的实现,是面向对象的基础 设计模式的基础.准备把继承多态和接口多态分开,因为从CLR实现的角度继承多态相比于接口多态要简单得多,也更容易理解,本篇只讨论继承多态, .NET Framework 2.0 和 4.0 这两个版本在实现上稍微有点区别(这里先…

2015蓝桥杯省赛---java---B---8(饮料换购)

题目 饮料换购 饮料换购乐羊羊饮料厂正在举办一次促销优惠活动。乐羊羊C型饮料&#xff0c;凭3个瓶盖可以再换一瓶C型饮料&#xff0c;并且可以一直循环下去&#xff0c;但不允许赊账。请你计算一下&#xff0c;如果小明不浪费瓶盖&#xff0c;尽量地参加活动&#xff0c;那么…

python123测验9程序题_python程序设计实验二

Python程序设计实验安徽工程大学班级&#xff1a;物流191 姓名&#xff1a;许岚岚 学号&#xff1a;3190505110日期&#xff1a;2020年3月21日指导教师&#xff1a;修 宇实验二 顺序结构程序设计(验证性实验)(二学时)【实验目的】(1)掌握数据的输入输出的方法&#…

零配置 之Spring基于Java类定义Bean配置元数据

转载自 【第十二章】零配置 之 12.4 基于Java类定义Bean配置元数据 ——跟我学spring3 12.4 基于Java类定义Bean配置元数据 12.4.1 概述 基于Java类定义Bean配置元数据&#xff0c;其实就是通过Java类定义Spring配置元数据&#xff0c;且直接消除XML配置文件。 基于Jav…

Rider IDE恢复了对.NET Core调试的支持

近期发布的JetBrain的Rider IDE&#xff08;EAP17&#xff09;移除了对.NET Core调试支持。该功能与NuGet的一个软件包在许可上存在冲突&#xff0c;而EAP17使用NuGet提供的.NET Core项目调试功能&#xff0c;所以必须要移除该功能。为此&#xff0c;JetBrains迅速推出了Rider …

2016蓝桥杯省赛---java---B---1(煤球数目)

题目 煤球数目 思路分析 代码实现 package com.atguigu.lanqiao;import java.util.Scanner;public class Main { // 简单枚举public static void main(String[] args) { // 171700int pre 1;int plus 2;long sum 1;for (int k 2; k < 100; k) {sum (pre plus); //…

vue 多页面多模块分模块打包 分插件安装_Vue渲染方式

Vue中的渲染方式总结可分四种:原有模板语法&#xff0c;挂载渲染使用render属性&#xff0c;createElement函数直接渲染使用render属性&#xff0c;配合组件的template属性&#xff0c;createElement函数渲染使用render属性&#xff0c;配合单文件组件&#xff0c;createElemen…

零配置 之 Spring注解实现Bean定义

转载自 零配置 之 12.3 注解实现Bean定义 ——跟我学spring3 12.3 注解实现Bean定义 12.3.1 概述 前边介绍的Bean定义全是基于XML方式定义配置元数据&#xff0c;且在【12.2注解实现Bean依赖注入】一节中介绍了通过注解来减少配置数量&#xff0c;但并没有完全消除在XML…

开源库 Natasha2016 ,让IL编程跑起来

背景&#xff1a; IL编程在普通的程序员的代码里几乎不会出现&#xff0c;但从Json.net、Dapper、Asp.net等等开源项目都体现出了IL编程的重要性。 在IL编程的时候&#xff0c;上百行甚至上千行的IL代码实在让人头大&#xff0c;调试不方便不说&#xff0c;IL编程的逻辑也是不同…

代码随想录27期|Python|Day24|回溯法|理论基础|77.组合

图片来自代码随想录 回溯法题目目录 理论基础 定义 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。 回溯是递归的副产品&#xff0c;只要有递归就会有回溯。回溯函数也就是递归函数&#xff0c;指的都是一个函数。 基本问题 组合问题&#xff08;无序&…

指纹识别软件安装包下载

微信关注公众号&#xff1a;1111的博客&#xff0c;回复“指纹识别”&#xff0c;即可获取指纹识别安装包的下载链接。本软件的版本为指纹识别2.0应用程序&#xff0c;在安装的过程中有以下几个注意点【一定要看】&#xff1a;安装完成之后直接运行&#xff1a;指纹识别.exe文件…

python获取当前进程id_从python进程名中获取进程id

我试图在进程名的帮助下获取pid。我尝试过this解决方案。但它给了我这个错误Traceback (most recent call last):File "pidName.py", line 10, in getPIDs("safari")File "pidName.py", line 4, in getPIDspidlist map(int, s.check_output([&q…

三大框架题目整合考试题(含详解)

三大框架题目整合考试题&#xff08;含详解&#xff09; 1.在Hibernate的关联关系映射配置中&#xff0c;下列选项对于inverse说法错误的是(bd)。 (选择二项&#xff09; A. inverse属性指定了关联关系中的方向 //inverse设置为false,则为主动方,由主动方负责维护关联关系,默…

2016蓝桥杯省赛---java---B---2(生日蜡烛)

题目描述 生日蜡烛 思路分析 代码实现(方式一) package com.atguigu.TEST;class Main{public static void main(String[] args) {int sum236;int a0;//记录开始过生日的年龄for (int i 0; i < 100; i) {for (int j i; j < 100; j) {aaj;if(asum){System.out.printl…

ntp时间同步会导致mysql关闭吗?_ntp时间同步问题解决方法

http://www.pool.ntp.org/zone/asia0.asia.pool.ntp.org1.asia.pool.ntp.org2.asia.pool.ntp.org3.asia.pool.ntp.org2.1 注册表信息修改PDC配置外部时间源设置#config external NTP serverw32tm.exe /config /manualpeerlist:”0.asia.pool.ntp.org,1.asia.pool.ntp.org,2.asi…

javaSE视频教程正式启动

亲爱的小伙伴们&#xff1a;经过激烈的思想斗争之后&#xff0c;我决定了&#xff0c;决定什么呢&#xff1f;决定给大家送福利了&#xff01;对&#xff0c;是送福利了&#xff01;送什么福利呢&#xff1f;送教程&#xff0c;javaSE的教程免费送&#xff0c;主要还是由我来讲…

快速搭建本地 .NET Core 运行时调试环境

需要的软件环境&#xff1a; Oracle VM VirtualBoxCentOS 7llvm lldb 3.6.0 (3.5.0我试过 dumpobj时候一直报无效参数 Invalid parameter T_T) 先在VirtualBox创建新虚机&#xff1a;一路 Next &#xff0c;文件位置可以自定义下(默认是在Users/当前用户/.. 目录下)创建完选在设…

零配置 之 Spring 概述

转载自 【第十二章】零配置 之 12.1 概述 ——跟我学spring3 12.1 概述 12.1.1 什么是零配置 在SSH集成一章中大家注意到项目结构和包结构是不是很有规律&#xff0c;类库放到WEB-INF/lib文件夹下&#xff0c;jsp文件放到WEB-INF/jsp文件夹下&#xff0c;web.xml需要放到…

背包问题+图解

图解 代码实现 package com.atguigu.dynamic;/*** 创建人 wdl* 创建时间 2021/4/3* 描述*/ public class KnapsackProblem {public static void main(String[] args) {int[] w{1,4,3};//物品的重量int[] val{1500,3000,2000};//物品的价值 这里的val[i]就是前面的v[i]int m4;/…

mysql预编译语句拼接查询_SQL语句预编译(查询)

SQL语句预编译SQL语句预编译能预防SQL注入提高安全性&#xff0c;是因为SQL语句在程序运行前已经进行了预编译&#xff0c;在程序运行时第一次操作数据库之前&#xff0c;SQL语句已经被数据库分析&#xff0c;编译和优化&#xff0c;对应的执行计划也会缓存下来并允许数据库以参…