Spring框架总结(三)——bean标签和依赖注入

一、bean 标签和管理对象细节


1.1 bean 标签

作用:

  用于配置对象让spring来创建的。

  默认情况下它调用的是类中的无参构造函数。如果没有无参构造函数则不能创建成功。

属性:

  id:给对象在容器中提供一个唯一标识。用于获取对象。

  class:指定类的权限定类名。用于反射创建对象。默认情况下调用无参构造函数。

  scope:指定对象的作用范围。

    * singleton:默认值,单例的。

    * prototype:多例的

  init-method:指定类中的初始化方法名称。

  destory-method:指定类中销毁方法名称。

1.2 bean的作用范围和生命周期

单列对象:scope="singleton"

  一个应用只有一个对象的实例。它的作用范围就是整个引用。

  生命周期:

    对象出生:当应用加载时,创建容器时,对象就被创建了。

    对象活着:只有容器在,对象一直活着。

    对象死亡:当应用卸载,销毁容器时,对象就被销毁了。

多例对象:scope="prototype"

  每次访问对象时,都会重新创建对象实例。

  生命周期:

    对象出生:当使用对象时,创建新的对象实例。

    对象活着:只要对象在使用中,就一直活着。

    对象死亡:当对象长时间不用时,被java的垃圾回收器回收了。

演示:单例和多例对象

第一步:编写IUserService接口

1 package com.justnow.service;
2 
3 public interface IUserService {
4     public void findAll();
5 }

第二步:编写UserServiceImpl实现类

 1 package com.justnow.service.impl;
 2 
 3 import com.justnow.service.IUserService;
 4 
 5 public class UserServiceImpl implements IUserService {
 6 
 7     public void findAll() {
 8         System.out.println("假装打印了数据库中的所有数据");
 9     }
10 }

第三步:编写spring配置文件

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"
4        xsi:schemaLocation="http://www.springframework.org/schema/beans
5        http://www.springframework.org/schema/beans/spring-beans.xsd">
6     <!--配置 service -->
7     <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" scope="singleton"/>
8 </beans>

这里配置scope为单例对象

第四步:测试

 1 package com.justnow.test;
 2 
 3 import com.justnow.service.IUserService;
 4 import org.junit.Test;
 5 import org.springframework.context.support.ClassPathXmlApplicationContext;
 6 
 7 public class Test01 {
 8     @Test
 9     public void testBean(){
10         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
11         IUserService userService = (IUserService) context.getBean("userService");
12         IUserService userService1 = (IUserService) context.getBean("userService");
13         System.out.println(userService);
14         System.out.println(userService1);
15     }
16 }

单例测试结果:

userService和userService2,打印出来的结果是一致的!

双例测试结果:

修改scope为"prototype"

1.3 实例化bean的三种方式

第一种方式:使用默认无参构造函数

会根据默认无参构造函数来创建类对象。如果bean中没有默认无参构造函数,将会创建失败。

如:

1 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" />

此时UserServiceImpl中必须有无参的构造函数。

第二种方式:spring管理静态工厂-使用静态工厂的方法创建对象

模拟一个静态工厂,创建业务层实现类

 1 package com.justnow.factory;
 2 
 3 import com.justnow.service.IUserService;
 4 import com.justnow.service.impl.UserServiceImpl;
 5 
 6 public class StaticFactory {
 7     public static IUserService createUserService(){
 8         return new UserServiceImpl();
 9     }
10 }

bean的配置,使用StaticFactory类中的静态方法createUserService创建对象,并存入spring容器:

id 属性:指定bean的id,用于从容器中获取

class属性:指定静态工厂的全限定类名

factory-method 属性:指定生产对象的静态方法

1 <bean id="userService" class="com.justnow.factory.StaticFactory" factory-method="createUserService" />

第三种方式:spring管理实例工厂-使用实例工厂的方法创建对象

先把工厂的创建交给spring来管理。然后在使用工厂的bean来调用里面的方法

factory-bean属性:用来指定实例工厂beand的id。

factory-method属性:用于指定实例工厂中创建对象的方法。

模拟一个实例工厂,创建业务层实现类

此工厂创建对象,必须现有工厂实例对象,再调用方法

 1 package com.justnow.factory;
 2 
 3 import com.justnow.service.IUserService;
 4 import com.justnow.service.impl.UserServiceImpl;
 5 
 6 /**
 7  * 模拟一个实例工厂,创建业务层实现类
 8  * 此工厂创建对象,必须有工厂实例对象,再调用方法
 9  */
10 public class InstanceFactory {
11     public IUserService createUserService(){
12         return new UserServiceImpl();
13     }
14 }

bean的配置文件

    <!--第三种方式,spring管理实例工厂,使用实例工厂的方法创建对象-->
    <bean id="instanceFactory" class="com.justnow.factory.InstanceFactory"/>
    <bean id="userService" factory-bean="instanceFactory" factory-method="createUserService" />

https://github.com/justn0w/javawebdemo/tree/master/spring/Spring_demo2 

d20c371406409b204c554c0a41c91ad5b6b86de1

二、spring的依赖注入

2.1 什么是依赖注入:

依赖注入:Dependency Injection。它是spring框架核心IoC的具体实现。

我们的程序在编写时,通过控制反转,把对象的创建交给了spring,但是在代码中不可能出现没有依赖的情况。IoC解耦只是降低他们的依赖关系。

但不会消除。例如:我们的业务层仍会调用持久层的方法。简单的说就是spring框架把持久层对象传入业务层,而不用我们自己去获取。

2.2 通过构造函数实现依赖注入

使用类中的构造函数,给成员变量赋值。赋值操作是由spring框架来为我们注入的。

UserServiceImpl实现类:

该类共有三个属性,分别是name,age,birthday;

 1 package com.justnow.service.impl;
 2 
 3 import com.justnow.service.IUserService;
 4 
 5 import java.util.Date;
 6 
 7 public class UserServiceImpl implements IUserService {
 8 
 9     private String name;
10     private Integer age;
11     private Date birthdy;
12 
13     public UserServiceImpl() {
14     }
15 
16     public UserServiceImpl(String name, Integer age, Date birthdy){
17         this.name = name;
18         this.age = age;
19         this.birthdy = birthdy;
20     }
21 
22     public void save(){
23         System.out.println(name+","+age+","+birthdy);
24     }
25 
26 /*    public void findAll() {
27         System.out.println("假装打印了数据库中的所有数据");
28     }*/
29 }

在配置文件中赋值:

applicationContext.xml

1     <!--通过构造函数实现依赖注入-->
2     <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" >
3         <constructor-arg name="name" value="张三"></constructor-arg>
4         <constructor-arg name="age" value="18"></constructor-arg>
5         <constructor-arg name="birthdy" ref="now"></constructor-arg>
6     </bean>
7     <bean id="now" class="java.util.Date" />

使用构造函数的方式,给service中的属性赋值

要求:类中需要提供一个对应参数列表的构造函数

标签:constructor-arg

  属性:index:指定参数在构造函数列表的索引位置

     type:指定参数在构造函数中的数据类型

     name:指定参数在构造函数中的名称

     value:给name属性赋值,前提是基本数据类型和String类型

     ref:同样的是给name赋值,但是该值是bean类型,必须在配置文件中配置。如上例中的id为now的bean标签

本小节代码:

https://github.com/justn0w/javawebdemo/tree/master/spring/Spring_demo2

2e64f8d7cf0a7a1f710e8abfc3d9707653b5063a

2.2 set 方法注入

 在UserServiceImpl实现类中,设置属性的set的方法即可代码,如下:

 1 package com.justnow.service.impl;
 2 
 3 import com.justnow.service.IUserService;
 4 
 5 import java.util.Date;
 6 
 7 public class UserServiceImpl implements IUserService {
 8 
 9     private String name;
10     private Integer age;
11     private Date birthdy;
12 
13     //set 方法注入
14     public void setName(String name) {
15         this.name = name;
16     }
17 
18     public void setAge(Integer age) {
19         this.age = age;
20     }
21 
22     public void setBirthdy(Date birthdy) {
23         this.birthdy = birthdy;
24     }
25 
26     public void save(){
27         System.out.println(name+","+age+","+birthdy);
28     }
29     
30 }

同时还需要修改spring的配置文件

 1     <!--通过set方法实现依赖注入-->
 2     <!-- 通过配置文件给 bean 中的属性传值:使用 set 方法的方式
 3     涉及的标签:
 4         property
 5     属性:
 6         name:找的是类中 set 方法后面的部分
 7         ref:给属性赋值是其他 bean 类型的
 8         value:给属性赋值是基本数据类型和 string 类型的
 9     实际开发中,此种方式用的较多。
10 -->
11     <bean id="userService" class="com.justnow.service.impl.UserServiceImpl">
12         <property name="name" value="test"/>
13         <property name="age" value="21"/>
14         <property name="birthdy" ref="now" />
15     </bean>
16 
17     <bean id="now" class="java.util.Date" />

测试结果:

 https://github.com/justn0w/javawebdemo/tree/master/spring/Spring_demo2

fe6038b18cff7d32c1b4515bf53bea9c8b0bdd0e

2.2 使用p名称空间注入数据

在xml中导入p名称空间,使用p:propertyName来注入数据,本质仍然是调用类中的set方法实现注入功能。

所以,UserServiceIpml实现类,不需要改变。只需要修改spring的配置文件即可

第一步:修改xml的命名空间,即添加p命名空间

添加了一句:

xmlns:p="http://www.springframework.org/schema/p"

第二步:在bean中使用p标签给属性赋值

1 <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" p:name="testp" p:age="23" p:birthdy-ref="now"/>
2 <bean id="now" class="java.util.Date" />

测试结果:

 47e50fff82f0cee3155226f620a00989da3828a6

2.3 注入集合属性

考虑到某些情况下需要一些类型为集合的属性,接下来就演示下,如何注入集合属性的。其本质还是通过set方法注入属性的

第一步:在实现类中添加数组、List、set、Map、Properties等数据类型的属性。

 1 package com.justnow.service.impl;
 2 
 3 import com.justnow.service.IUserService;
 4 
 5 import java.util.*;
 6 
 7 public class UserServiceImpl2 implements IUserService {
 8 
 9     private String[] myStrs;
10     private List<String> myList;
11     private Set<String> mySet;
12     private Map<String, String> myMap;
13     private Properties myProps;
14 
15     public void setMyStrs(String[] myStrs) {
16         this.myStrs = myStrs;
17     }
18 
19     public void setMyList(List<String> myList) {
20         this.myList = myList;
21     }
22 
23     public void setMySet(Set<String> mySet) {
24         this.mySet = mySet;
25     }
26 
27     public void setMyMap(Map<String, String> myMap) {
28         this.myMap = myMap;
29     }
30 
31     public void setMyProps(Properties myProps) {
32         this.myProps = myProps;
33     }
34 
35 
36     public void save() {
37         System.out.println(Arrays.toString(myStrs));
38         System.out.println(myList);
39         System.out.println(mySet);
40         System.out.println(myMap);
41         System.out.println(myProps);
42     }
43 }

第二步:修改spring配置文件

  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"
  4        xmlns:p="http://www.springframework.org/schema/p"
  5        xsi:schemaLocation="http://www.springframework.org/schema/beans
  6        http://www.springframework.org/schema/beans/spring-beans.xsd">
  7     <!--配置 service -->
  8 <!-- 第一种方式,使用默认无参构造函数
  9     <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" scope="prototype"/>
 10 -->
 11     <!--第二种方式,spring管理静态工厂-使用静态工厂的方法对象创建-->
 12 <!--
 13     <bean id="userService" class="com.justnow.factory.StaticFactory" factory-method="createUserService" />
 14 -->
 15     <!--第三种方式,spring管理实例工厂,使用实例工厂的方法创建对象-->
 16 <!--
 17     <bean id="instanceFactory" class="com.justnow.factory.InstanceFactory"/>
 18     <bean id="userService" factory-bean="instanceFactory" factory-method="createUserService" />
 19 -->
 20 
 21     <!--通过构造函数实现依赖注入-->
 22 <!--
 23     <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" >
 24         <constructor-arg name="name" value="张三"></constructor-arg>
 25         <constructor-arg name="age" value="18"></constructor-arg>
 26         <constructor-arg name="birthdy" ref="now"></constructor-arg>
 27     </bean>
 28     <bean id="now" class="java.util.Date" />
 29 -->
 30     <!--通过set方法实现依赖注入-->
 31     <!-- 通过配置文件给 bean 中的属性传值:使用 set 方法的方式
 32     涉及的标签:
 33         property
 34     属性:
 35         name:找的是类中 set 方法后面的部分
 36         ref:给属性赋值是其他 bean 类型的
 37         value:给属性赋值是基本数据类型和 string 类型的
 38     实际开发中,此种方式用的较多。
 39 
 40     <bean id="userService" class="com.justnow.service.impl.UserServiceImpl">
 41         <property name="name" value="test"/>
 42         <property name="age" value="21"/>
 43         <property name="birthdy" ref="now" />
 44     </bean>
 45 
 46     <bean id="now" class="java.util.Date" />
 47 -->
 48     <!--使用p命名空间-->
 49 <!--
 50     <bean id="userService" class="com.justnow.service.impl.UserServiceImpl" p:name="testp" p:age="23" p:birthdy-ref="now"/>
 51     <bean id="now" class="java.util.Date" />
 52 -->
 53     <!-- 注入集合数据
 54         List 结构的:
 55             array,list,set
 56         Map 结构的
 57             map,entry,props,prop
 58 -->
 59     <bean id="userService" class="com.justnow.service.impl.UserServiceImpl2">
 60         <!-- 在注入集合数据时,只要结构相同,标签可以互换 -->
 61         <!-- 给数组注入数据 -->
 62         <property name="myStrs">
 63             <array>
 64                 <value>AAA</value>
 65                 <value>BBB</value>
 66                 <value>CCC</value>
 67             </array>
 68         </property>
 69         <!-- 注入 list 集合数据 -->
 70         <property name="myList">
 71             <list>
 72                 <value>AAA</value>
 73                 <value>BBB</value>
 74                 <value>CCC</value>
 75             </list>
 76         </property>
 77         <!-- 注入 set 集合数据 -->
 78         <property name="mySet">
 79             <set>
 80                 <value>AAA</value>
 81                 <value>BBB</value>
 82                 <value>CCC</value>
 83             </set>
 84         </property>
 85         <!-- 注入 Map 数据 -->
 86         <property name="myMap">
 87             <props>
 88                 <prop key="testA">aaa</prop>
 89                 <prop key="testB">bbb</prop>
 90             </props>
 91         </property>
 92         <!-- 注入 properties 数据 -->
 93         <property name="myProps">
 94             <map>
 95                 <entry key="testA" value="aaa"></entry>
 96                 <entry key="testB">
 97                     <value>bbb</value>
 98                 </entry>
 99             </map>
100         </property>
101     </bean>
102 </beans>

77a345e6da51295e1aa4c5e8c25038e23da3f6ec

总结:


1、这些内容在将来的开发过程中会很少用到,但是,还是梳理一下。

  

原文地址:https://www.cnblogs.com/justn0w/p/11481244.html