Spring----(1)Spring的配置

1 Spring相关概念

1.1 Spring Framework系统架构

在这里插入图片描述

  • 核心层
    Core Container:核心容器
  • AOP层:
    AOP:面向切面编程。它依赖核心层容器,目的是在不改变原有代码的前提下对其进行功能增强
    Aspects:AOP思想实现
  • Web层: web开发
  • 数据层:
    Data Access:数据访问
    Data Integration:数据集成,
    Transactions:事务,Spring中事务管理是Spring AOP的一个具体实现
  • Test层: 单元测试与集成测试

1.2 Spring Framework 学习线路

在这里插入图片描述

1.3 Spring Framework核心概念

业务层需要调用数据层的方法,需要在业务层new数据层的对象,如果数据层的实现类发生变化,那么业务层的代码也需要跟着改变,发生变更后,都需要进行编译打包和重部署,所以,编写的过程中存在的问题是:耦合度高
解决方案:不使用new产生对象,转换为由外部提供对象。即Ioc

  • IoC ( Inversion of Control ):控制反转
    使用对象时, 由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转
  • Spring技术对IoC思想进行了实现
    Spring提供了一个容器, 称为IoC容器,用来充当IoC思想中的心外部
    IoC容器负责对象的创建、 初始化等-系列工作, 被创建或被管理的对象在 IoC容器中统称为Bean
  • DI ( Dependency Injection ):依赖注入
    在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入

2 入门案例

2.1 IoC入门案例

  • 思路分析
    在这里插入图片描述
  • 代码实现
  1. 导入spring依赖坐标spring-context
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
  1. 定义Spring管理的类(接口)
public interface BookService {
    void save();
}
public class BookServiceImpl implements BookService {
    private BookDao bookDao = new BookDaoImpl();

    public void save(){
        System.out.println("book service save...");
        bookDao.save();
    }
}
  1. 创建Spring配置文件,配置对应类作为Spring管理的bean
    bean标签表示配置bean,id属性表示给bean起名字,class属性表示给bean定义类型

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">

    <!--配置bean-->
    <bean id="bookDao" class="com.zs.dao.impl.BookDaoImpl"></bean>
    <bean id="bookService" class="com.zs.service.impl.BookServiceImpl"></bean>
</beans>
  1. 初始化IoC容器(Spring核心容器/Spring容器),通过容器获取bean
public class App2 {
    public static void main(String[] args) {
        //获取IOC容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取Bean
        BookService bookService = (BookService) ctx.getBean("bookService");
        bookService.save();
    }
}

Spring的IoC入门案例已经完成。但是在BookServiceImpl的类中依然存在BookDaoImpl对象的new操作,它们之间的耦合度还是比较高,这就需要用到下面的DI:依赖注入

2.2 DI入门案例

  • 思路分析
    在这里插入图片描述
  • 代码实现:
  1. 删除用new的形式创建的代码
public class BookServiceImpl implements BookService {
    //删除业务层中使用new的方式创建的dao对象
    private BookDao bookDao;

    public void save(){
        System.out.println("book service save...");
        bookDao.save();
    }
}

  1. 提供依赖对象对应的setter方法
public class BookServiceImpl implements BookService {
    //删除业务层中使用new的方式创建的dao对象
    private BookDao bookDao;

    public void save(){
        System.out.println("book service save...");
        bookDao.save();
    }

    //提供对应的set方法
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

  1. 配置service与dao之间的关系
    property标签表示配置当前bean的属性
    name属性表示配置哪一个具体的属性
    ref属性表示参照那个bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">
    <!--配置bean-->
    <bean id="bookDao" class="com.zs.dao.impl.BookDaoImpl"/>
    <bean id="bookService" class="com.zs.service.impl.BookServiceImpl">
        <!--配置service与dao的关系-->
        <property name="bookDao" ref="bookDao"/>
    </bean>
</beans>

3 核心容器Bean

3.1 bean配置

3.1.1 bean基础配置

在这里插入图片描述

3.1.2 bean的别名配置

在这里插入图片描述

注意:
在这里插入图片描述

3.1.3 bean的作用范围

在这里插入图片描述

  1. 为什么bean默认为单例 ?
    bean为单例的意思是在Spring的IOC容器中只会有该类的一个对象
    bean对象只有一个就避免了对象的频繁创建与销毁,达到了bean对象的复用,性能高

  2. 适合交给容器进行管理的bean:表现层对象;业务层对象;数据层对象;工具对象

  3. 不适合交给容器进行管理的bean:封装实体的域对象

3.2 bean实例化

3.2.1 实例化bean的三种方式1----构造方法(常用)

  • bean的本质是对象,创建bean使用构造方法完成
  • 提供可访问的构造方法
public class BookDaoImpl implements BookDao {
    public BookDaoImpl() {
        System.out.println("book dao constructor is running ....");
    }
    public void save() {
        System.out.println("book dao save ...");
    }
 
}
  • 配置
    <bean id="bookDao" class="com.zs.dao.impl.BookDaoImpl"/>
  • 无参方法如果不存在,将抛出异常BeanCreationException

3.2.2 实例化bean的三种方式2----静态工厂(了解)

  • 静态工厂
public class OrderDaoFactory {
    public static OrderDao getOrderDao(){
        return new OrderDaoImpl();
    }
}
  • 配置
<bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>

这种方式一般是用来兼容早期的一些老系统,所以了解为主。

3.2.3 实例化bean的三种方式3----实例工厂(了解)与FactoryBean(常用)

  • 实例工厂
public class UserDaoFactory {
    public UserDao getUserDao(){
        return new UserDaoImpl();
    }
}
  • 配置
<!--   第一步,创建实例化工厂对象,实际无意义,主要为了第二步用它-->
<bean id="userFactory" class="com.itheima.factory.UserDaoFactory"/>
<!--   第二步,调用实例化工厂对象中的方法来创建bean,不用class属性是因为getUserDao返回值是UserDao,ioc容器是可以找到UserDao的-->
<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
  • 运行测试结果
public class AppForInstanceUser {
    public static void main(String[] args) {
        ApplicationContext ctx = new 
            ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) ctx.getBean("userDao");
        userDao.save();
    }
}

3.2.4 实例化bean的第四种方式----FactoryBean(常用)

  • FactoryBean
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
    //代替原始实例工厂中创建对象的方法
    public UserDao getObject() throws Exception {
        //返回dao实现类的实例
        return new UserDaoImpl();
    }
    //返回所创建类的Class对象
    public Class<?> getObjectType() {
        //返回dao接口的字节码
        return UserDao.class;
    }
}
  • 配置
<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>
  • FactoryBean设置单例、非单例:
    将isSingleton()方法进行重写,修改返回为false(默认为true单例)
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
    //代替原始实例工厂中创建对象的方法
    public UserDao getObject() throws Exception {
        return new UserDaoImpl();
    }
 
    public Class<?> getObjectType() {
        return UserDao.class;
    }
 
    public boolean isSingleton() {
        return false;
    }
}

3.3 bean生命周期

  • 生命周期:从创建到消亡的完整过程,例如人从出生到死亡的整个过程就是一个生命周期

  • bean生命周期:bean对象从创建到销毁的整体过程
    在这里插入图片描述

  • bean生命周期控制:在bean创建后到销毁前做一些事情。

  • 生命周期控制方式一:
    提供生命周期控制方法

public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ...");
    }

    public void init(){
        System.out.println("init...");
    }
    public void destroy(){
        System.out.println("destroy...");
    }
}
  • 配置生命周期控制方法
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
  • 运行结果:
    在这里插入图片描述

init方法执行了,但是destroy方法却未执行。原因:Spring的IOC容器是运行在JVM中,运行main方法后,JVM启动,Spring加载配置文件生成IOC容器,从容器获取bean对象,然后调方法执行;main方法执行完后,JVM退出,这个时候IOC容器中的bean还没有来得及销毁就已经结束了;所以没有调用对应的destroy方法。
在这里插入图片描述

  • 解决方法一:使用close()方法在虚拟机退出之前将容器关闭(比较暴力)
    由于ApplicationContext中没有close方法,需要将ApplicationContext更换成ClassPathXmlApplicationContext,再调用ctx的close()方法
public class App2 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
        ctx.close();
    }
}

在这里插入图片描述

  • 解决方法二:设置关闭钩子,注册钩子关闭容器
    容器启动后加了个标记,让JVM在退出之前回调此函数来关闭容器
public class App2 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        ctx.registerShutdownHook();
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
        //ctx.close();
    }
}

两种方式的区别::
close()是在调用的时候强制关闭,如果后面还有IOC的相关代码会报错
registerShutdownHook()是在JVM退出前调用关闭,可以放在任何位置
当然两种方法我们都不用写,我们最终做的是web应用,关闭容器应该伴随Tomcat关闭一块的

  • 生命周期控制方式二:
    接口控制(了解)
public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
    private BookDao bookDao;

    public void save(){
        System.out.println("book service save...");
        bookDao.save();
    }

    //提供对应的set方法
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("service destroy...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("service init...");
    }
}

在这里插入图片描述

  • 小细节
    对于InitializingBean接口中的afterPropertiesSet方法,即属性设置之后
    对于BookServiceImpl来说,bookDao是它的一个属性,setBookDao方法是Spring的IOC容器为其注入属性的方法
    试验:
public void setBookDao(BookDao bookDao) {
        System.out.println("set...");
        this.bookDao = bookDao;
    }

结果:
在这里插入图片描述

  • 小结
    在这里插入图片描述

4 依赖注入

  • 思考
    在这里插入图片描述
  • 依赖注入方式
    setter注入:简单类型和引用类型 .
    构造器注入:简单类型和引用类型

4.1 setter注入

4.1.1 setter注入----引用类型

  • 在bean中定义引用类型属性并提供可访问的set方法
public class BookServiceImpl implements BookService {
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}
  • 配置中使用property标签ref属性注入引用类型对象
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
    <property name="bookDao" ref="bookDao"/>
</bean>
 
<bean id="bookDao" class="com.itheima.dao.imipl.BookDaoImpl"/>

4.1.2 setter注入----简单类型

  • 在bean中定义简单类型属性并提供可访问的set方法
public class BookDaoImpl implements BookDao {
 
    private String databaseName;
    private int connectionNum;
 
    public void setConnectionNum(int connectionNum) {
        this.connectionNum = connectionNum;
    }
 
    public void setDatabaseName(String databaseName) {
        this.databaseName = databaseName;
    }
 
    public void save() {
        System.out.println("book dao save ..."+databaseName+","+connectionNum);
    }
}
  • 配置中使用property标签value属性注入简单类型数据
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">
 
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
        <property name="databaseName" value="mysql"/>
         <property name="connectionNum" value="10"/>
    </bean>
    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
        <property name="bookDao" ref="bookDao"/>
        <property name="userDao" ref="userDao"/>
    </bean>
</beans>

4.2 构造器注入

4.2.1 构造器注入----引用类型

  • 在bean中定义引用类型属性并提供可访问的构造方法
public class BookServiceImpl implements BookService{
    private BookDao bookDao;
 
    public BookServiceImpl(BookDao bookDao) {
        this.bookDao = bookDao;
    }
 
    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}
  • 配置中使用constructor-arg标签ref属性注入引用类型对象
    name属性的值为构造函数中构造方法形参的参数名
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">
 
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
        <constructor-arg name="bookDao" ref="bookDao"/>
    </bean>
</beans>

4.2.2 构造器注入----简单类型

public class BookDaoImpl implements BookDao {
    private String databaseName;
    private int connectionNum;
 
    public BookDaoImpl(String databaseName, int connectionNum) {
        this.databaseName = databaseName;
        this.connectionNum = connectionNum;
    }
 
    public void save() {
        System.out.println("book dao save ..."+databaseName+","+connectionNum);
    }
}
  • 在bean中定义简单类型属性并提供可访问的set方法
public class BookDaoImpl implements BookDao {
    private String databaseName;
    private int connectionNum;
 
    public BookDaoImpl(String databaseName, int connectionNum) {
        this.databaseName = databaseName;
        this.connectionNum = connectionNum;
    }
 
    public void save() {
        System.out.println("book dao save ..."+databaseName+","+connectionNum);
    }
}
  • 配置中使用constructor-arg标签value属性注入简单类型数据
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">
 
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
        <constructor-arg name="databaseName" value="mysql"/>
        <constructor-arg name="connectionNum" value="666"/>
    </bean>
    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
        <constructor-arg name="bookDao" ref="bookDao"/>
        <constructor-arg name="userDao" ref="userDao"/>
    </bean>
</beans>

当构造函数中方法的参数名发生变化后,配置文件中的name属性也需要跟着变,存在高耦合的问题
解决方案(有缺点,了解即可):参数名发生变化的情况并不多,并且解决方案有缺点类型限制或顺序限制

4.2.3 构造器注入----参数适配(了解)

  • 配置中使用constructor-arg标签type属性设置按形参类型注入
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    <constructor-arg type="int" value="10"/>
    <constructor-arg type="java.lang.String" value="mysql"/>
</bean>
  • 配置中使用constructor-arg标签index属性设置按形参位置注入
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
    <constructor-arg index="1" value="100"/>
    <constructor-arg index="0" value="mysql"/>
</bean>

依赖注入方式选择:
在这里插入图片描述

4.3 依赖自动装配

  • IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配
  • 自动装配方式:按类型(常用);按名称;按构造方法;不启用自动装配
  • 按类型注入:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">
 
    <bean class="com.itheima.dao.impl.BookDaoImpl"/>
    <!--autowire属性:开启自动装配,通常使用按类型装配-->
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>
 
</beans>

需要注入属性的类中对应属性的setter方法不能省略
被注入的对象必须要被Spring的IOC容器管理
按类型注入必须保障容器中相同类型的bean唯一,否则会报NoUniqueBeanDefinitionException

  • 按名称注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">
 
    <bean class="com.itheima.dao.impl.BookDaoImpl"/>
    <!--autowire属性:开启自动装配,通常使用按类型装配-->
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byName"/>
 
</beans>

4.4 集合注入

  • BookDaoImpl:
public class BookDaoImpl implements BookDao {
 
    private int[] array;
 
    private List<String> list;
 
    private Set<String> set;
 
    private Map<String,String> map;
 
    private Properties properties;
 
     public void save() {
        System.out.println("book dao save ...");
 
        System.out.println("遍历数组:" + Arrays.toString(array));
 
        System.out.println("遍历List" + list);
 
        System.out.println("遍历Set" + set);
 
        System.out.println("遍历Map" + map);
 
        System.out.println("遍历Properties" + properties);
    }
    //setter方法
}
  • 集合注入:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">
    <!--配置bean-->
    <bean id="bookDao" class="com.zs.dao.impl.BookDaoImpl">
        <property name="array">
            <array>
                <value>100</value>
                <value>200</value>
                <value>300</value>
            </array>
        </property>
        <property name="list">
            <list>
                <value>itcast</value>
                <value>itheima</value>
                <value>boxuegu</value>
                <value>chuanzhihui</value>
            </list>
        </property>
        <property name="set">
            <set>
                <value>itcast</value>
                <value>itheima</value>
                <value>boxuegu</value>
                <value>boxuegu</value>
            </set>
        </property>
        <property name="map">
            <map>
                <entry key="country" value="china"/>
                <entry key="province" value="henan"/>
                <entry key="city" value="kaifeng"/>
            </map>
        </property>
        <property name="properties">
            <props>
                <prop key="country">china</prop>
                <prop key="province">henan</prop>
                <prop key="city">kaifeng</prop>
            </props>
        </property>
    </bean>
</beans>

5 案例----数据源对象的管理(了解)

了解即可,开发中更多用注解开发。

5.1 实现Driud管理

  1. 导入依赖
<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>
    </dependencies>
  1. 配置数据源对象作为spring管理的bean
    Ctrl+b跟进到DruidDataSource类,按Ctrl+f12查看发现适合用setter方法注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">
    <!--管理DruidDataSource对象-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
</beans>
  1. 从IOC容器中获取对应的bean对象
public class App {
    public static void main(String[] args) {
       ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
       DataSource dataSource = (DataSource) ctx.getBean("dataSource");
       System.out.println(dataSource);
    }
}

运行一下,测试结果:
在这里插入图片描述

5.2 实现C3P0管理

  1. 导入坐标,从mvn的仓库中进行搜索
<!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
<dependency>
    <groupId>c3p0</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.1.2</version>
</dependency>
  1. 配置数据源对象作为spring管理的bean
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_db"/>
    <property name="user" value="root"/>
    <property name="password" value="root"/>
    <property name="maxPoolSize" value="1000"/>
</bean>
  1. 运行程序
    在这里插入图片描述
    问题:报的错为ClassNotFoundException,没有找到com.mysql.jdbc.Driver类。
    错误原因:缺少mysql的驱动包
    解决:在pom.xml把驱动包导入
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.16</version>
</dependency>

运行:
在这里插入图片描述

总结:

  1. 数据连接池在配置属性的时候,除了可以注入数据库连接四要素外还可以配置很多其他的属性,按需配置
  2. Druid和C3P0在没有导入mysql驱动包的前提下,一个没报错一个报错,说明Druid在初始化的时候没有去加载驱动,而C3P0刚好相反
  3. Druid程序运行虽然没有报错,但是当调用DruidDataSource的getConnection()方法获取连接的时候,也会报找不到驱动类的错误

5.3 加载porperties文件

问题:上面的案例中,数据库的配置写在Spring的配置文件中不利于后期维护
解决:将配置信息写在porperties文件中,使用spring加载porperties文件
实现: 在Spring的配置文件中加载properties文件;使用加载到的值实现属性注入

具体实现:

  1. resources下创建一个jdbc.properties文件,并添加对应的属性键值对
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///spring_db?ssl=false
jdbc.username=root
jdbc.password=root
  1. 开启context命名空间
    在这里插入图片描述
  2. 使用context空间加载porperties文件
<context:property-placeholder location="jdbc.properties"/>
  1. 使用属性占位符${}读取properties文件中的属性,完成属性注入
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
</bean>

设置系统属性模式:
在properties文件中配置键值对的时候,如果key设置为username值为root666,在applicationContext.xml注入该属性

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
 
    <context:property-placeholder location="jdbc.properties"/>
 
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
        <property name="name" value="${username}"/>
    </bean>
</beans>

运行程序输出的结果不是root666而是电脑的用户名
原因:<context:property-placeholder/>标签会加载系统的环境变量,而且环境变量的值优先度更高
解决:设置系统属性模式为NEVER,表示不加载系统属性;也可以避免key设置为username

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
 
    <context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/>
</beans>

加载多个properties配置文件:
在这里插入图片描述

6 容器

  1. 容器的两种创建方式

方式一:类路径下的XML配置文件(推荐使用)

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

方式二:文件系统下的XML配置文件(耦合度较高,不推荐使用)

ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\workspace\\spring\\spring_10_container\\src\\main\\resources\\applicationContext.xml");
  1. Bean的三种获取方式

方式一:根据id获取

BookDao bookDao = (BookDao) ctx.getBean("bookDao");

方式二:

BookDao bookDao = ctx.getBean("bookDao"BookDao.class);

解决类型强转问题但是参数又多加了一个,相对来说没有简化多少

方式三:

BookDao bookDao = ctx.getBean(BookDao.class);

类似前面所学习的依赖注入中的按类型注入。必须要确保IOC容器中该类型对应的bean对象只能有一个

  1. 容器类层次结构图
    在这里插入图片描述
    ClassPathXmlApplicationContext实现ApplicationContext,ApplicationContext继承BeanFactory

  2. BeanFactory创建容器(了解)

public class AppForBeanFactory {
    public static void main(String[] args) {
        Resource resources = new ClassPathResource("applicationContext.xml");
        BeanFactory bf = new XmlBeanFactory(resources);
        BookDao bookDao = bf.getBean(BookDao.class);
        bookDao.save();
    }
}
  1. BeanFactory和ApplicationContext的区别
    BeanFactory是延迟加载,只有在获取bean对象的时候才会去创建
    ApplicationContext是立即加载,容器加载的时候就会创建bean对象
    ApplicationContext要想成为延迟加载,需要在bean中配置lazy-init=true

7 核心容器总结

7.1 容器相关

  • BeanFactory是IOC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载
  • ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载
  • ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能
  • ApplicationContext接口常用初始化类
    • ClassPathXmlApplicationContext(常用)
    • FileSystemXmlApplicationContext

7.2 bean相关

在这里插入图片描述

7.3 依赖注入相关

在这里插入图片描述
参考文章

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值