Spring02-注入和注解方式操作

Posted Sue

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring02-注入和注解方式操作相关的知识,希望对你有一定的参考价值。

一. 依赖注入

测试类:Person.java

创建配置文件:applicationContext-injection.xml

创建测试代码:InjectionTest.java

1. set方法注入

1.1 基本类型值注入使用value

配置:

1   <!-- value值为基本类型 -->
2   <bean name="person"  class="spring.bean.Person" >
3        <property name="name" value="jeck" />
4        <property name="age" value="11"/>
5   </bean>

测试代码:

 1   @Test
 2   public  void  test1(){
 3         //TODO 测试基本数据类型注入数据
 4         ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-injection.xml");
 5 
 6         Person person = context.getBean("person", Person.class);
 7 
 8         System.out.println("person = " + person);
 9         //输出结果:------------> Person.Person
10         //          person = Person{name=‘jeck‘, age=11}
11  }

1.2 引入类型值注入ref

创建 Car.java:

 1 public class Car {
 2     private String name;
 3     private String color;
 4     
 5     public Car() {
 6         super();
 7         System.out.println("Car的空参构造方法");
 8     }
 9     //getter、setter、toString
10 }

修改Person.java,在Person中引入Car:

1 public class Person {
2     private String name;
3     private Integer age;
4     private Car car;
5      //构造方法 getter setter toString方法 
6 }

配置:利用ref属性给 person的car属性赋值

 1   <bean name="person1" class="spring.bean.Person">
 2       <property name="name" value="helen"></property>
 3       <property name="age" value="18"></property>
 4       <property name="car" ref="car"></property>
 5   </bean>
 6     
 7   <bean name="car" class="spring.bean.Car">
 8       <property name="name" value="MINI"></property>
 9       <property name="color" value="灰色" ></property>
10   </bean>

测试: 使用之前测试用例即可!

2.构造函数注入

2.1 单个有参构造方法注入

在Person中创建有参构造函数:

1  public  Person(String  name , Car car){
2         this.name = name;
3         this.car = car;
4         System.out.println("Person的有参构造方法:"+name+car);
5  }

配置:

1 <bean name="person" class="spring.bean.Person">
2            <constructor-arg name="name" value="rose"/>
3            <constructor-arg name="car"  ref="car"/>
4  </bean>
5  <!-- 构造函数car时候引入 -->
6  <bean name="car"  class="spring.bean.Car" >
7            <property name="name" value="mime"/>
8            <property name="color" value="白色"/>
9  </bean>

测试:

 1   @Test
 2   public  void test2(){
 3         //TODO 测试参构造方法
 4         ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-injection.xml");
 5 
 6         Person person = context.getBean("person", Person.class);
 7 
 8         System.out.println(person);
 9         //结果:调用有参数构造方法,输出
10   }

2.2. index属性:按参数索引注入

参数名一致,但位置不一致时,使用 index

例如以下两个构造函数(第二个是新添加):

 1     public Person(String name, Car car) {
 2         super();
 3         System.out.println("Person(String name, Car car)");
 4         this.name = name;
 5         this.car = car;
 6     }  
 7     public Person(Car car, String name) {
 8         super();
 9         System.out.println("Person(Car car, String name)");
10         this.name = name;
11         this.car = car;
12     }

配置:使用 index 确定调用哪个构造函数

1     <bean name="person2" class="spring.bean.Person">
2         <constructor-arg name="name" value="helen" index="0"></constructor-arg>
3         <constructor-arg name="car" ref="car" index="1"></constructor-arg>
4     </bean>

测试:

重新执行第一步的测试用例,执行结果调用了第一个构造函数

2.3. type属性:按参数类型注入

参数名和位置一致,但类型不一致时,使用type

例如以下两个构造函数(第二个是新添加):

 1     public Person(Car car, String name) {
 2         super();
 3         System.out.println("Person(Car car, String name)");
 4         this.name = name;
 5         this.car = car;
 6     }
 7   
 8     public Person(Car car, Integer name) {
 9         super();
10         System.out.println("Person(Car car, Integer name)");
11         this.name = name + "";
12         this.car = car;
13     }

配置:使用type指定参数的类型

    <bean name="person2" class="spring.bean.Person">
        <constructor-arg name="name" value="988" type="java.lang.Integer"></constructor-arg>
        <constructor-arg name="car" ref="car" ></constructor-arg>
    </bean>

测试:

重新执行前面的测试用例,执行结果调用了第二个构造函数

3. p名称空间注入

导入p名称空间:

使用p:属性名 完成注入,走set方法

  • 基本类型值: p:属性名="值"

  • 引入类型值: P:属性名-ref="bean名称"

配置:

 1 //1.第一步配置文件中 添加命名空间p 
 2  xmlns:p="http://www.springframework.org/schema/p"
 3 <beans xmlns="http://www.springframework.org/schema/beans"
 4        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5 xmlns:p="http://www.springframework.org/schema/p"      xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd">
 6        //使用 p命称空间进行赋值
 7         <bean name="person" class="spring.bean.Person"  p:name="人名" p:age="11"    p:car-ref="car">
 8        </bean>
 9        <bean name="car"  class="spring.bean.Car" >
10            <property name="name" value="mime" />
11            <property name="color" value="白色"/>
12        </bean>

测试:

1 @Test
2 public  void test2(){
3     //TODO 测试p命名空间注入
4     ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-injection.xml");
5     Person person = context.getBean("person", Person.class);
6     System.out.println(person);
7     
8  }

4. spel注入

spring Expression Language:spring表达式语言

配置:

1   <bean name="car"  class="spring.bean.Car" >
2            <property name="name" value="mime" />
3            <property name="color" value="白色"/>
4   </bean>
5    <!--利用spel引入car的属性 -->
6    <bean  name="person1"  class="spring.bean.Person"  p:car-ref="car">
7             <property name="name" value="#{car.name}"/>
8             <property name="age" value="#{person.age}"/>
9    </bean>

测试

1 @Test
2 public  void test3(){
3     //TODO 测试spel注入
4     ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-injection.xml");
5     Person person = context.getBean("person1", Person.class);
6     System.out.println(person);
7     
8  }

5. 复杂类型注入

创建配置文件:application-collection.xml

创建测试代码:CollectionTest.java

创建测试实体类:TestCollection

创建TestCollection:

 1 /**
 2  * 练习:arr list map properties的注入
 3  */
 4 public class TestCollection {
 5 
 6     private Object [] arrs;
 7     private List<Object> list;
 8     private Map<String,Object> map;
 9     private Properties properties;
10 
11     public Object[] getArrs() {
12         return arrs;
13     }
14 
15     public void setArrs(Object[] arrs) {
16         this.arrs = arrs;
17     }
18 
19     public List<Object> getList() {
20         return list;
21     }
22 
23     public void setList(List<Object> list) {
24         this.list = list;
25     }
26 
27     public Map<String, Object> getMap() {
28         return map;
29     }
30 
31     public void setMap(Map<String, Object> map) {
32         this.map = map;
33     }
34 
35     public Properties getProperties() {
36         return properties;
37     }
38 
39     public void setProperties(Properties properties) {
40         this.properties = properties;
41     }
42 
43     @Override
44     public String toString() {
45         return "TestCollection{" +
46                 "arrs=" + Arrays.toString(arrs) +
47                 ", list=" + list +
48                 ", map=" + map +
49                 ", properties=" + properties +
50                 ‘}‘;
51     }
52 }

配置:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        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.xsd">
 4        <bean name="car" class="spring.bean.Car">
 5              <property name="name" value="保时捷"/>
 6              <property name="color" value="红色" />
 7        </bean>
 8        <bean name="testColl" class="pring.bean.TestCollection">
 9            <!-- 数组变量注入 -->
10            <property name="arrs">
11                <list>
12                    <value>数组1</value>
13                    <!--引入其他类型-->
14                    <ref bean="car"/>
15                </list>
16            </property>
17            <!-- 集合变量赋值-->
18            <property name="list">
19                 <list>
20                     <value>集合1</value>
21                     <!--集合变量内部包含集合-->
22                     <list>
23                         <value>集合中的集合1</value>
24                         <value>集合中的集合2</value>
25                         <value>集合中的集合3</value>
26                     </list>
27                     <ref bean="car" />
28                 </list>
29            </property>
30 
31            <!--map赋值 -->
32            <property name="map">
33                <map>
34                    <entry key="car" value-ref="car" />
35                    <entry key="name" value="保时捷" />
36                    <entry key="age"  value="11"/>
37                </map>
38            </property>
39            <!-- properties赋值 -->
40            <property name="properties">
41                 <props>
42                     <prop key="name">pro1</prop>
43                     <prop key="age">111</prop>
44                 </props>
45            </property>
46        </bean>
47 
48 </beans>

测试:

1  @Test
2  public  void  test4(){
3         //TODO 复杂类型注入练习
4      ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-collection.xml");
5      TestCollection textColl = context.getBean("testColl", TestCollection.class);
6      System.out.println("testColl = " + textColl);
7 
8    }

二.使用注解

使用注解的方式完成IOC

1. 准备工作

  • 创建项目: spring-02-annotation

  • 导入jar包: spring-core,spring-context,spring-suppot-context,spring-beans,spring-expression, log4j,commons-logging,本次多加一个:spring-aop

  • 引入日志配置文件:log4j.properties

  • 实体类: 原项目 Person.java 和 Car.java即可

  • 创建配置文件: applicationContext.xml

  • 创建测试代码类:AnnotationTest.java

2. 使用注解

2.1 引入Context的约束

参考文件位置:spring-framework-4.2.4.RELEASEdocsspring-framework-referencehtmlxsd-configuration.html 40.2.8 the context schema

配置:

1 <?xml version="1.0" encoding="UTF-8"?>
2 <!--较之前多了 xmlns:context -->
3 <beans xmlns="http://www.springframework.org/schema/beans"
4        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:context="http://www.springframework.org/schema/context"
5        xsi:schemaLocation="
6         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
7         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here -->
8 </beans>

2.2 配置注解扫描

在applicationContext.xml中配置:

指定扫描 下所有类中的注解,扫描包时,会扫描包所有的子孙包.

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!--较之前多了 xmlns:context -->
 3 <beans xmlns="http://www.springframework.org/schema/beans"
 4        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      xmlns:context="http://www.springframework.org/schema/context"
 5        xsi:schemaLocation="
 6         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 7         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here -->        
 8      <!--扫描包设置-->
 9       <context:component-scan base-package="spring.bean">       </context:component-scan>
10 </beans>

2.3 使用注解

在Person类的头部添加如下注解

 1 /**
 2   * @Component(person) == <bean name="person" class="spring.bean.Person" />
 3   */
 4 
 5 @Component("person")
 6 public class Person {
 7     private String name;
 8     private Integer age;
 9     private Car car;
10     public  Person(){
11         System.out.println("无参数构造方法!");
12     }
13   //getter,setter,toString
14 }  

测试:

1   @Test
2   public  void  test1(){
3      //TODO 测试注解入门
4      ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
5      Person person = context.getBean("person", Person.class);
6      System.out.println("person = " + person);
7  }

3. 其他注解

介绍其他常用注解,测试方式同前

3.1 类头部可用的注解

1 @Service("person")         // service层
2 @Controller("person")     // controller层
3 @Repository("person")    // dao层

3.2 类头部可用的注解

指定对象作用域

1 @Scope(scopeName="singleton")
2 @Scope(scopeName="prototype")

3.3 注入属性value值

1.设置成员变量上:通过反射给变量赋值

1 @Value("name值")
2 private String name;

@Value("name值") 等同于 @Value(value="name值")

2.加在set方法上:通过set方法赋值

1 @Value("tom")
2 public void setName(String name)
3 {
4   this.name = name;
5 } 

3.4 自动装配

  1. @Autowired

使用 @Autowired 自动装配对象类型的属性: 下面的Person中的Car使用了自动装配

 1 //将Car定义成接口
 2 @Component
 3 public interface Car {
 4      void log();
 5 }
 6 //Baoma实现Car
 7 @Component
 8 public class Baoma implements Car {
 9     public void log() {
10         System.out.println("宝马");
11     }
12 }
13 //XianDai实现Car
14 @Component
15 public class XianDai implements Car {
16     public void log() {
17         System.out.println("现代");
18     }
19 }

装配类:

1 @Scope(scopeName = "prototype")
2 @Component("person")
3 public class Person {
4     @Value("name值")
5     private String name;
6     private Integer age;
7     @Autowired      
8     private Car car;  //自动装配 可以选择Car,如果Car是接口,找Car的实现类!

注意: 以上操作会出现一个问题,如果Car是接口,且Car只有一个实现类,那么@Autowired会自动将实现类装配给Person的car变量上,但是如果Car是接口,并且有两个以上实现类,那么自动装配就会报错,无法选择由哪个实现类赋值.所以需要配合另一个注释@Qualifier("bean name"), 这个属性可以将@Autowired按类型赋值改成按bean名字赋值.

3.5 @Qualifier

  • 如果匹配多个类型一致的对象,将无法选择具体注入哪一个对象

  • 使用@Qualifier()注解告诉spring容器自动装配哪个名称的对象。

    1 @Scope(scopeName = "prototype")
    2 @Component("person")
    3 public class Person {
    4     @Value("name值")
    5     private String name;
    6     private Integer age;
    7     @Autowired  
    8     @Qualifier("baoma")   //指定实现类
    9     private Car car;  //自动装配 可以选择Car,如果Car是接口,找Car的实现类!

    3.6 @Resource

    @Resource 是java的注释,但是Spring框架支持,@Resource指定注入哪个名称的对象

    @Resource("name") == @Autowired + @Qualifier("name")

    1 @Resource(name="baoma") 
    2 private Car car;

    3.7 初始化和销毁方法

    初始化和销毁方法等同于配置文件添加的init-method和destroy-method功能,

    例:Person类中init方法和destroy方法添加如下注解:

    1  @PostConstruct
    2  public  void init(){
    3    System.out.println("初始化方法");
    4  }
    5  @PreDestroy
    6  public void destroy(){
    7    System.out.println("销毁方法");
    8  }

    三. Spring整合JUnit测试

    spring整合junit,为我们提供了方便的测试方式

    1、导包:在spring-02-annotation项目中再加入如下包

    spring-test-4.2.8.jar

    2、创建测试类

     1 //创建容器
     2 @RunWith(SpringJUnit4ClassRunner.class)
     3 //指定创建容器时使用哪个配置文件
     4 @ContextConfiguration("classpath:applicationContext.xml")
     5 public class RunWithTest {
     6     //将名为user的对象注入到u变量中
     7     @Resource(name="person")
     8     private Person p;
     9     @Test
    10     public void testCreatePerson(){
    11         System.out.println(p);
    12     }
    13 }

     

以上是关于Spring02-注入和注解方式操作的主要内容,如果未能解决你的问题,请参考以下文章

Spring--IOC注解方式注入

常见的三种注解注入方式对比

spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象(代码片段

Spring注解注入

spring 如何用注解的方式给普通类注入bean

spring 抽象类注入问题