Spring IoC应用

1. Spring IoC 基础

1.1 BeanFactory与ApplicationContext的区别
BeanFactory是Spring中IoC容器的顶层接口,用来定义一些基础功能和基础规范。
ApplicationContext是BeanFactory的子接口,具备BeanFactory提供的所有功能。

通常,我们称BeanFactory为SpringIOC的基础容器,ApplicationContext是容器的⾼级接⼝,⽐BeanFactory要拥有更多的功能,⽐如说国际化⽀持和资源访问(xml,java配置类)等等

1.2 启动IOC容器的方式
  • javaEE环境:
    • ClassPathXMLApplicationContext (xml方式,从启动类的根路径下加载配置文件)
    • FileSystemXMLApplicationContext (xml方式,从磁盘路径下加载配置文件)
    • AnnotationConfigApplicationContext (纯注解方式)
  • Javaweb环境
    • xml启动:
Archetype Created Web Application contextConfigLocation classpath:applicationContext.xml org.springframework.web.context.ContextLoaderListener ``` - 纯注解启动 ```xml Archetype Created Web Application contextClass org.springframework.web.context.support.AnnotationConfigWebApplicationContext contextConfigLocation com.example.SpringConfig org.springframework.web.context.ContextLoaderListener ``` ##### 1.3 纯xml模式 ###### 1.3.1 xml文件约束头 ```xml ``` ###### 1.3.2 实例化bean的三种方式 - 使用无参构造函数 在默认情况下,它会通过反射调⽤⽆参构造函数来创建对象。如果类中没有⽆参构造函数,将创建失败。 ```xml ``` - 使用静态方法创建 在实际开发中,我们使⽤的对象有些时候并不是直接通过构造函数就可以创建出来的,它可能在创建的过程 中会做很多额外的操作。此时会提供⼀个创建对象的⽅法,恰好这个⽅法是static修饰的⽅法 ```xml ``` - 使用实例化方法创建 此种⽅式和上⾯静态⽅法创建其实类似,区别是⽤于获取对象的⽅法不再是static修饰的了,⽽是类中的⼀个普通⽅法。此种⽅式⽐静态⽅法创建的使⽤⼏率要⾼⼀些。 ```xml ``` ###### 1.3.3 bean的作用范围和生命周期 ##### 作用范围 在spring框架管理Bean对象的创建时,Bean对象默认都是单例的,但是它⽀持配置的⽅式改变作⽤范围。作⽤范围官⽅提供的说明如下图 ![](http://koujiaqi.cn/upload/20210408_14550013.png) ⽤到最多的作⽤范围就是singleton(单例模式)和prototype(原型模式,也叫多例模式) ```xml ``` ##### 生命周期 ###### 单例模式: singleton 初始化:当创建容器时,对象就被创建了。 存活:只要容器在,对象⼀直存活。 销毁:当销毁容器时,对象就被销毁了。 ⼀句话总结:单例模式的bean对象⽣命周期与容器相同。 ###### 多例模式: prototype 初始化:当使⽤对象时,创建新的对象实例。 存活:只要对象在使⽤中,就⼀直存活。 销毁:当对象⻓时间不⽤时,被java的垃圾回收器回收了。 ⼀句话总结:多例模式的bean对象,spring框架只负责创建,不负责销毁。
1.3.4 bean标签的属性
id属性: ⽤于给bean提供⼀个唯⼀标识。在⼀个标签内部,标识必须唯⼀。
class属性:⽤于指定创建Bean对象的全限定类名。
name属性:⽤于给bean提供⼀个或多个名称。多个名称⽤空格分隔。
factory-bean属性:⽤于指定创建当前bean对象的⼯⼚bean的唯⼀标识。当指定了此属性之后,class属性失效。
factory-method属性:⽤于指定创建当前bean对象的⼯⼚⽅法,如配合factory-bean属性使⽤,则class属性失效。如配合class属性使⽤,则⽅法必须是static的。
scope属性:⽤于指定bean对象的作⽤范围。默认情况下就是singleton。当要⽤到多例模式时,可以配置为prototype。
init-method属性:⽤于指定bean对象的初始化⽅法,此⽅法会在bean对象装配后调⽤。必须是⼀个⽆参⽅法。
destory-method属性:⽤于指定bean对象的销毁⽅法,此⽅法会在bean对象销毁前执⾏。它只能为scope是singleton时起作⽤。
1.3.5 DI 依赖注入的xml配置
依赖注入分类
  • 按注入方式
    1. 构造函数注入 是利⽤构造函数实现对类成员的赋值。它的使⽤要求是,类中提供的构造函数参数个数必须和配置的参数个数⼀致,且数据类型匹配。同时需要注意的是,当没有⽆参构造时,则必须提供构造函数参数的注⼊,否则Spring框架会报错。
public class JdbcAccountDaoImpl implements AccountDao {

    private ConnectionUtils connectionUtils;

//    public void setConnectionUtils(ConnectionUtils connectionUtils) {
//        this.connectionUtils = connectionUtils;
//    }

    public JdbcAccountDaoImpl(ConnectionUtils connectionUtils) {
        this.connectionUtils = connectionUtils;
    }

    //省略其他代码
	......
}
<bean id="accountDao" class="com.example.dao.impl.JdbcAccountDaoImpl">
        <!-- <property name="ConnectionUtils" ref="connectionUtils"></property>-->
        <!-- constructor-arg 通过构造函数注入  index 参数的索引,必须与构造中的参数顺序一致   name 属性的名称  ref 如果是引用类型,用ref指向    value  如果是基本数据类型或者String  使用value赋值  -->
        <!-- 通过参数索引注入 -->
        <!-- <constructor-arg index="0" ref="connectionUtils"></constructor-arg>-->
        <!--  通过参数名称注入 -->
        <constructor-arg name="connectionUtils" ref="connectionUtils"></constructor-arg>
</bean>

ii. setter() 利⽤字段的set⽅法实现赋值的注⼊⽅式。此种⽅式在实际开发中是使⽤最多的注⼊⽅式。

public class JdbcAccountDaoImpl implements AccountDao {

    private ConnectionUtils connectionUtils;

	//提供setter()
    public void setConnectionUtils(ConnectionUtils connectionUtils) {
        this.connectionUtils = connectionUtils;
    }

//    public JdbcAccountDaoImpl(ConnectionUtils connectionUtils) {
//        this.connectionUtils = connectionUtils;
//    }
}
<bean id="accountDao" class="com.example.dao.impl.JdbcAccountDaoImpl">
    <!--使用property为参数赋值  name是属性的名称   ref 是引用类型的指向   value  基本数据类型或者String类型的赋值-->
    <property name="ConnectionUtils" ref="connectionUtils"></property>
</bean>
  • 按注入的数据类型分类
    • 基本数据类型和String 基本数据类型或者字符串
    • bean类型 注入的是对象类型,这个对象存在在IOC容器中
    • 复杂数据类型 Array、List、Set、Map、Properties

public class JdbcAccountDaoImpl implements AccountDao {

private ConnectionUtils connectionUtils;

public void setConnectionUtils(ConnectionUtils connectionUtils) {
    this.connectionUtils = connectionUtils;
}

private String[] array;
private List<String> list;
private Set<String> set;
private Map<String, String> map;
private Properties properties;

public void setArray(String[] array) {
    this.array = array;
}

public void setList(List<String> list) {
    this.list = list;
}

public void setSet(Set<String> set) {
    this.set = set;
}

public void setMap(Map<String, String> map) {
    this.map = map;
}

public void setProperties(Properties properties) {
    this.properties = properties;
}
//省略部分代码
......

}

```xml
<bean id="accountDao" class="com.example.dao.impl.JdbcAccountDaoImpl">
        <!--使用property为参数赋值  name是属性的名称   ref 是引用类型的指向   value  基本数据类型或者String类型的赋值-->
        <property name="ConnectionUtils" ref="connectionUtils"></property>

        <property name="array" >
            <array>
                <value>array1</value>
                <value>array2</value>
            </array>
        </property>
        <property name="list">
            <list>
                <value>list2</value>
                <value>list1</value>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="key1" value="value1"></entry>
                <entry key="key2" value="value2"></entry>
            </map>
        </property>
        <property name="set">
            <set>
                <value>set1</value>
                <value>set2</value>
            </set>
        </property>
        <property name="properties">
            <props>
                <prop key="peopKey1">propValue1</prop>
                <prop key="peopKey2">propValue2</prop>
            </props>
        </property>
    </bean>

1.4 xml和注解结合模式

xml+注解结合模式,xml⽂件依然存在,所以,spring IOC容器的启动仍然从加载xml开始

1.4.1 哪些bean使用xml配置,哪些使用注解

第三⽅jar中的bean定义在xml,⽐如druid数据库连接池 ⾃⼰开发的bean定义使⽤注解

1.4.2 xml中标签与注解的对应(IoC)
xml形式对应的注解
标签@Componect("id") 配置在类上, id为bean的id,如果不配置,则默认按照当前类的类名,首字母小写。 另外,针对分层代码开发提供了@Component的三种别名:@Controller、@Service、@Repository分别用于controller层、service层、dao层,这四个注解的用法完全一样,只是为了更好的区分。
scope属性@Scope("singleton") 单例 默认 @Scope("prototype") 多例 加在类上
init-method 属性@PostConstruct,注解加在⽅法上,该⽅法就是初始化后调⽤的⽅法
destory-method 属性@PreDestory,注解加在⽅法上,该⽅法就是销毁前调⽤的⽅法