当前位置: 首页 > 图灵资讯 > 技术篇> 一篇文章带你掌握主流基础框架——Spring

一篇文章带你掌握主流基础框架——Spring

来源:图灵教育
时间:2023-06-30 16:24:53

本文将介绍Spring的框架和本体内容,包括核心容器、注释开发、AOP和事务等。

所以简单说明一下Spring的必要性:

  • Spring技术是JavaEE开发的必备技能,企业开发技术选型率高达90%!
  • Spring有助于简化发展,降低企业级发展的复杂性
  • Spring可以整合框架,有效整合其他技术,提高企业应用开发和运营效率

Spring的核心内容:

  • Ioc技术
  • DI技术
  • AOP
  • 事务处理

Spring可以进行框架集成:

  • MaBatis
  • MyBatis-plus
  • Struts
  • Struts2
  • Hibernate

在下一篇文章中,我们将学习Spring的框架思想,学习Spring的基本操作,并结合案例掌握它

温馨提醒:在学习本文之前,请先学习Javaweb的相关内容

(HTTP,Tomcat,Servlet,Request,Response,MVC,Cookie,Session,Ajax,Vue等内容)

初识Spring

官网:Spring | Home

Spring的发展已经形成了一个开发生态系统,Spring提供了相当多的项目,每个项目都用于完成特定的功能

一篇文章带你掌握主流基础框架——Spring_业务层

常用的主流技术包括:

  • Spring Framework:Spring框架
  • Spring Boot:Spring简化代码开发
  • Spring Cloud:Spring分布设计
Spring FrameWork系统架构

在系统学习Spring之前,我们需要了解FrameWork系统的结构

  • Spring Framework是Spring生态系统中最基本的项目,也是其他项目的基础

一篇文章带你掌握主流基础框架——Spring_业务层_02

我们现在使用的Spring FrameWork是4.0版,已经趋于稳定

下面我们来解释一下架构图:

  • Core Container:核心容器
  • AOP:面向切面编程
  • Aspects:实现AOP思想
  • Data Access:数据访问
  • Data Intergration:数据集成
  • Web:Web开发
  • Test:单元测试与集成测试

我们可以在官方中得到这样的评价:

  • 强大的基于 JavaBeans 采用控制反转(Inversion of Control,IoC)原则的配置管理使应用程序的构建更加快捷简单。
  • 数据库事务的一般抽象层允许插件式事务管理器简化事务的划分,使其与底层无关。
  • 一个可以用于从 applet 到 Java EE 不同运行环境的核心等 Bean 工厂。
核心概念介绍

首先,让我们考虑一下我们以前的业务层和数据层:

// publicic数据层接口 interface BookDao {    public void save();}

// publicic实现数据层的public class BookDaoImpl implements BookDao {    public void save() {        System.out.println("book dao save ...");    }}

// 业务层接口publiclicclic interface BookService {    public void save();}

// 业务层实现publicliccp class BookServiceImpl implements BookService {    private BookDao bookDao;    public void save() {        bookDao.save();    }}

如果我们修改BookDaoimpl内容,也应修改相应业务层实现中BookDao的new实现,甚至修改以下方法的对象

使用Spring前的问题

代码书写现状:

  • 耦合度偏高

解放方案:

  • 使用对象时,不要在程序中主动使用new生成对象,并将其转换为从外部提供的对象
实现Spring思想

IoC(Inversion of Control)控制反转思想:

  • 使用对象时,由主动new创建对象转换为外部提供对象
  • 在此过程中,对象创建的控制权由程序转移到外部,称为控制反转

DI(Dependency Injection)依赖注入:

  • 在容器中建立Bean和Bean之间的依赖关系和整个过程,称为依赖注入

Spring技术实现了Ioc思想:

  • Spring提供了一个被称为物联网容器的容器,用作物联网思想的外部
  • 物联网容器负责创建、初始化等一系列工作。物联网容器中创建和管理的对象称为Bean

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

// 包含daoservice的IoC容器/*可以建立连接*/

// 实现public实现public class BookServiceImpl implements BookService {    private BookDao bookDao;    public void save() {        bookDao.save();    }}

目的:完全解耦

  • IoC:使用IOC容器管理beann
  • DI:在IOC容器中绑定依赖关系的bean

最终效果:

  • 使用对象不仅可以直接从物联网容器中获得,还可以绑定已获得的Bean之间的依赖关系
IoC入门

首先,我们需要了解物联网的使用规则:

  1. IoC负责管理什么:Service和Dao
  2. 物联网容器是如何被管理对象告知的:(配置)
  3. 如何将管理对象交给物联网容器:(接口)
  4. 获得IoC容器后,如何获得Bean?:(接口方法)
  5. 使用Spring所需导入的坐标:(pom.xml)

以下是物联网入门的详细步骤:

  1. 在pommm创建Maven项目.将坐标导入xml

<dependencies>    <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-context</artifactId>      <version>5.2.10.RELEASE</version>    </dependency>  </dependencies>

  1. 创建Spring.xml配置包(applicationContext.xml,XML在导入坐标后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">    <!--2.配置bean-->    <!--bean标签标签配置bean标签配置bean标签配置    id属性标记为bean命名    class属性表示bean定义类型(注意需要实现类)-->        <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl"/></beans>

  1. 主函数

package com.itheima;import com.itheima.dao.BookDao;import com.itheima.service.BookService;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class App2 {    public static void main(String[] args) {        //3获取IoC容器        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");                //4.获取bean(根据bean配置id获取)///BookDao bookDao = (BookDao) ctx.getBean("bookDao");//bookDao.save();                // 注:需要类型转换        BookService bookService = (BookService) ctx.getBean("bookService");        bookService.save();    }}

DI入门

首先需要了解DI的使用规则:

  1. bean基于IOC管理
  2. 使用new形式在Service中创建Dao对象是否保留:(否)
  3. 要求Dao对象在Service中进入Service:(提供方法)
  4. 如何描述Service和Dao之间的关系:(配置)

以下是DI入门的详细步骤(基于IOC入门):

  1. 删除new方法

public class BookServiceImpl implements BookService {    //5.删除业务层中使用new创建的dao对象    private BookDao bookDao;    public void save() {        System.out.println("book service save ...");        bookDao.save();    }}

  1. 创建对象的set方法

public class BookServiceImpl implements BookService {    //5.删除业务层中使用new创建的dao对象    private BookDao bookDao;    public void save() {        System.out.println("book service save ...");        bookDao.save();    }        //6.提供相应的set方法    public void setBookDao(BookDao bookDao) {        this.bookDao = bookDao;    }}

  1. 创建Dao和Service之间的连接

<?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">    <!--2.配置bean-->    <!--bean标签标配bean    id属性标记为bean命名    class属性表示bean定义类型-->    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">        <!--7.配置server与dao的关系-->        <!--注:在server中配置关系property标签表示配置当前bean的属性        name属性表示配置的具体属性        ref属性表示参考哪个bean?-->        <property name="bookDao" ref="bookDao"/>    </bean></beans>

Bean整体介绍

Bean是物联网中保存的对象,我们通过配置获得Bean

让我们从三个方面来解释Bean。:

bean基本配置

首先我们先介绍一下bean本身的性质:

类别

描述

名称

bean

类型

标签

所属

beans标签

功能

Spring核心容器管理对象的定义

格式

<beans><bean> </bean></beans>

属性列表

id:bean的id,在一个容器中,id值唯一的classs可以通过id值获得相应的bean:bean的类型,即配置bean的全路径类名

范例

<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">

然后我们来介绍一下bean的别名:

类别

描述

名称

name

类型

标签

所属

bean标签

功能

定义bean的别名,可以定义多个,使用逗号,分号,空格分隔

范例

<bean id="bookService" name="service service4 bookEbi" class="com.itheima.service.impl.BookServiceImpl">

一般情况下,使用id和name都可以获得bean,但是建议使用唯一的id

无论是通过id还是name获得bean,如果找不到bean,就抛出异常NosuchbeanDefinitionException。

最后,我们来介绍一下bean的作用范围scope:

类别

描述

名称

scope

类型

标签

所属

bean标签

功能

定义bean的作用范围,可选范围如下:singleton:单独列(默认)prototype:非单列

范例

<bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl" scope="prototype"/>

这里的scope是指生成对象的数量

默认情况下,我们的scope是singleton,因为许多对象只需要创建一次,多次创建会导致内存膨胀。

bean适合交给容器进行管理(singleton):

业务层对象数据层对象对象的对象

bean不适合交给容器进行管理(prototype):

包装实体的域对象(带状态的bean)

bean实例化

bean的实例化通常分为四种方法,我们在下面逐一介绍:

  1. 结构方法(常用)

在配置条件下,我们需要在数据类中提供结构方法

// public数据类 class BookDaoImpl implements BookDao {    public BookDaoImpl() {        System.out.println("book dao constructor is running ...");    }    public void save() {        System.out.println("book dao save ...");    }}

<?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">    <!--方法一:构造方法实例化beann-->    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/></beans>

如果不存在参结构方法,则抛出异常Beancreationexception

  1. 静态工厂(理解)

在之前的案例中,我们有一个对象工厂的说法,我们可以设立工厂,并调用它的方法来获得bean

// 静态工厂package com.itheima.factory;import com.itheima.dao.OrderDao;import com.itheima.dao.impl.OrderDaoImpl;/////静态工厂创建对象publiccicc class OrderDaoFactory {    public static OrderDao getOrderDao(){        System.out.println("factory setup...");        return new OrderDaoImpl();    }}

<?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">    <!--方法二:使用静态工厂实例beann-->    <bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/></beans>

  1. 实例工厂(理解)

和静态工厂一样,但不同的是方法不是静态的,我们需要提前创建一个bean

// 实例工厂package com.itheima.factory;import com.itheima.dao.UserDao;import com.itheima.dao.impl.UserDaoImpl;///实例工厂创建对象publiccic class UserDaoFactory {    public UserDao getUserDao(){        return new UserDaoImpl();    }}

<?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">    <!--方法三:使用实例工厂实例beann-->    <bean id="userFactory" class="com.itheima.factory.UserDaoFactory"/>    <!--factory-bean:实例工厂本身beanfactory-method:使用调用bean的方法-->    <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/></beans>

  1. FactoryBean(重要实用)

除了我们之前定义的工厂外,Spring还提供了FactoryBeann的官方版本

// FactoryBean工厂(需要接口,< >填写数据类接口)package com.itheima.factory;import com.itheima.dao.UserDao;import com.itheima.dao.impl.UserDaoImpl;import org.springframework.beans.factory.FactoryBean;///FactoryBean创建对象publiciciccictictic class UserDaoFactoryBean implements FactoryBean<UserDao> {    //替换原始实例工厂中创建对象的方法        // UserDaoImpl()返回创建对象类型    public UserDao getObject() throws Exception {        return new UserDaoImpl();    }    // 这里填写接口类型    public Class<?> getObjectType() {        return UserDao.class;    }    // 可修改scope属性    public boolean isSingleton() {        return false;    }}

<?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">    <!--方法四:使用FactoryBean实例bean-->    <bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/></beans>

bean生命周期

先接单介绍生命周期的相关概念:

  • 生命周期:从创造到消亡的完整过程
  • bean生命周期:bean从创建到销毁的整个过程
  • bean生命周期控制:在bean创建后到销毁前做点什么

接下来,我们将介绍生命周期控制方法:

  1. 数据层提供控制方法

在xml配置文件中设置由数据层提供的方法

// package数据层 com.itheima.dao.impl;import com.itheima.dao.BookDao;public class BookDaoImpl implements BookDao {        public void save() {        System.out.println("book dao save ...");    }        ///表示bean初始化对应的操作    public void init(){        System.out.println("init...");    }    ///表示bean销毁前相应的操作    public void destory(){        System.out.println("destory...");    }}

<!--配置文件--><?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">    <!--init-method:设置bean初始生命周期回调函数-->    <!--destroy-method:设置bean销毁生命周期回调函数,仅适用于单例对象-->    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">        <property name="bookDao" ref="bookDao"/>    </bean></beans>

  1. 接口控制方法(理解)

Spring为创建提供了两个接口,我们只需要继承和实现这种方法

package com.itheima.service.impl;import com.itheima.dao.BookDao;import com.itheima.service.BookService;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.InitializingBean;// InitializingBean,DisposableBean 分别对应afterPropertiesset和destroy方法,代表public的创建和销毁 class BookServiceImpl implements BookService, InitializingBean, DisposableBean {    private BookDao bookDao;    public void setBookDao(BookDao bookDao) {        System.out.println("set ...");        this.bookDao = bookDao;    }    public void save() {        System.out.println("book service save ...");        bookDao.save();    }    public void destroy() throws Exception {        System.out.println("service destroy");    }    public void afterPropertiesSet() throws Exception {        System.out.println("service init");    }}

<?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" init-method="init" destroy-method="destory"/>        <!--直接调用即可-->    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">        <property name="bookDao" ref="bookDao"/>    </bean></beans>

我们需要提到bean的销毁时机:(了解)

  • 因为默认情况下,我们的bean不会被销毁,因为虚拟机会直接退出,claspathXmlaplicationcontext将被忽略

因此,要想销毁bean观察到destroy的实现,就需要手动关闭:

  1. 手动关闭容器方法:

package com.itheima;import com.itheima.dao.BookDao;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class AppForLifeCycle {    public static void main( String[] args ) {        // 注:以ClaspathXmlaplicationcontext为对象,因为只有这一类才有close方法        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");        BookDao bookDao = (BookDao) ctx.getBean("bookDao");        bookDao.save();        ///关闭容器        ctx.close();    }}

  1. 注册关闭钩子,在虚拟机退出前关闭容器,然后启动虚拟机

package com.itheima;import com.itheima.dao.BookDao;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class AppForLifeCycle {    public static void main( String[] args ) {        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");        BookDao bookDao = (BookDao) ctx.getBean("bookDao");        bookDao.save();        //注册关闭钩子函数,在虚拟机退出之前对此函数进行回调,关闭容器        ctx.registerShutdownHook();    }}

最后统计一下整个生命周期:

初始化容器:创建对象(内存分配)->实施结构方法->执行属性注入(set操作)->使用bean执行bean初始方法:执行业务操作关闭/销毁容器:执行bean销毁方法

依赖于注入方式

首先,我们需要知道有两种方法可以在类中传输数据:

  • 普通方法(Set)
  • 构造方法

然后我们应该知道,数据的类型一般分为两种:

  • 引入类型(数据层)
  • 简单类型(基本数据类型和String)

因此,我们将依赖注入分为四种方式:

  • 注入简单类型的setter引用类型
  • 注入简单类型的介绍类型的结构器
setter注入简单类型

首先,我们需要在bean中定义简单的类型属性,并提供可访问的set方法

package com.itheima.dao.impl;import com.itheima.dao.BookDao;public class BookDaoImpl implements BookDao {    private String databaseName;    private int connectionNum;    ///setter注入需要为注入对象提供set方法    public void setConnectionNum(int connectionNum) {        this.connectionNum = connectionNum;    }    ///setter注入需要为注入对象提供set方法    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">        <!--注入简单类型-->    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">        <!--property标签:设置注入属性-->        <!--name属性:设置注入的属性名,实际上是set方法对应的名称-->        <!--value属性:设置注入简单类型的数据值-->        <property name="connectionNum" value="100"/>        <property name="databaseName" value="mysql"/>    </bean></beans>

setter注入引用类型

首先,我们需要定义bean中引用的类型属性,并提供可访问的set方法

package com.itheima.service.impl;import com.itheima.dao.BookDao;import com.itheima.dao.UserDao;import com.itheima.service.BookService;public class BookServiceImpl implements BookService{    private BookDao bookDao;    private UserDao userDao;    //setter注入需要提供需要注入对象的set方法    public void setUserDao(UserDao userDao) {        this.userDao = userDao;    }    //setter注入需要提供需要注入对象的set方法    public void setBookDao(BookDao bookDao) {        this.bookDao = bookDao;    }    public void save() {        System.out.println("book service save ...");        bookDao.save();        userDao.save();    }}

然后在配置中使用property标签ref属性注入引用类型数据

<?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="connectionNum" value="100"/>        <property name="databaseName" value="mysql"/>    </bean>    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>    <!--注入引用类型-->    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">        <!--注入引用类型-->    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">        <!--property标签:设置注入属性-->        <!--name属性:设置注入的属性名,实际上是set方法对应的名称-->        <!--ref属性:设置注入引用类型bean的id或name-->        <property name="bookDao" ref="bookDao"/>        <property name="userDao" ref="userDao"/>    </bean></beans>

注入简单类型的构造器(理解)

在bean中定义简单的类型属性并提供可访问的set方法

public class BookDaoImpl implements BookDao{private int connectionNumber;        pubilc void setConnectionNumber(int connectionNumber){this.connectionNumber = connectionNumber;    }}

constructorarg标签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="connectionNum" value="10"/>    </bean>    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/></beans>

引用类型(理解)注入构造器

在bean中定义引用类型属性并提供可访问的结构方法

public class BookDaoImpl implements BookDao{private BookBao bookBao;        pubilc void setConnectionNumber(int connectionNumber){this.bookBao = bookBao;    }}

使用constructorarg标签ref属性在配置中注入简单类型的数据

<?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="bookService" class="com.itheima.service.impl.BookServiceImpl">        <constructor-arg name="userDao" ref="userDao"/>        <constructor-arg name="bookDao" ref="bookDao"/>    </bean></beans>

参数配置问题(理解)注入构造器

我们已经介绍了构造器的注入方法

但是,如果我们在bean中更改数据名称,配置将不再适应,因此提供了一些解决参数配置问题的方法:

  • constructorarg标签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>    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">        <constructor-arg name="userDao" ref="userDao"/>        <constructor-arg name="bookDao" ref="bookDao"/>    </bean>

  • constructorarg标签index属性设置在配置中

<!--解决参数类型重复问题,使用位置解决参数匹配问题-->    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">        <!--根据结构方法的参数位置注入-->        <constructor-arg index="0" value="mysql"/>        <constructor-arg index="1" value="100"/>    </bean>    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">        <constructor-arg name="userDao" ref="userDao"/>        <constructor-arg name="bookDao" ref="bookDao"/>    </bean>

依靠注入方式的选择

以下选择标准取决于注入方式:

  1. 强制依靠使用结构器,使用setter注入有可能不注入,导致null对象出现
  2. 可选依靠使用setter注入,灵活性高
  3. Spring框架提倡使用结构器,大多数第三方框架以结构器注入的形式初始化数据,相对严格
  4. 如有必要,可以两者并用,用结构器注入强制依赖注入,用setter注入可选依赖注入
  5. 在实际开发中,根据情况分析,如果受控对象没有提供setter方法,则只能使用构造器注入
  6. 尽量推荐settter注入自己开发的模块
依靠自动装配

之前我们已经学会了手动注射的方法,但是Spring实际上为我们提供了一种依赖自动装配的语法:

  • 根据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>

依靠自动装配的特点:

自动组装用于注入引用类型,不能按类型操作简单类型(byType)必须保证容器中相同类型的bean是唯一的,建议按名称组装时使用(byName)必须确保容器中有指定名称的bean。由于变量名与配置耦合,不建议使用低于setter注入和构造器注入的自动组装优先级。同时出现时,自动装配配置失效

依靠集合注入

除了基本类型和介绍类型外,我们有时还需要注入集合

下面我们简单介绍一下结合注入:

// 数据类 package com.itheima.dao.impl;import com.itheima.dao.BookDao;import java.util.*;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 setArray(int[] 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;    }    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);    }}

<!--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 id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">        <!--数组注入-->        <!--注意:name:对应实现类中的内部成员名称<>里面的array等是固定词汇。-->        <property name="array">            <array>                <value>100</value>                <value>200</value>                <value>300</value>            </array>        </property>        <!--集合注入list-->        <property name="list">            <list>                <value>itcast</value>                <value>itheima</value>                <value>boxuegu</value>                <value>chuanzhihui</value>            </list>        </property>        <!--集合注入set-->        <property name="set">            <set>                <value>itcast</value>                <value>itheima</value>                <value>boxuegu</value>                <value>boxuegu</value>            </set>        </property>        <!--集合注入map-->        <property name="map">            <map>                <entry key="country" value="china"/>                <entry key="province" value="henan"/>                <entry key="city" value="kaifeng"/>            </map>        </property>        <!--注入Properties-->        <property name="properties">            <props>                <prop key="country">china</prop>                <prop key="province">henan</prop>                <prop key="city">kaifeng</prop>            </props>        </property>    </bean></beans>

案例:数据源对象管理

对于一个新的数据源对象,我们使用两个步骤来创建bean(我们以druid为例):

  • 导入druid坐标

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.itheima</groupId>    <artifactId>spring_09_datasource</artifactId>    <version>1.0-SNAPSHOT</version>    <dependencies>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-context</artifactId>            <version>5.2.10.RELEASE</version>        </dependency>        <!--这里介绍druid坐标-->        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>druid</artifactId>            <version>1.1.16</version>        </dependency>        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <version>5.1.47</version>        </dependency>    </dependencies></project>

  • 作为Spring管理的beang,配置数据源对象

<?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            ">    <!--    DruidataSource对象的管理-->    <!--起id 设置class地址-->    <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="123456"/>    </bean></beans>

案例:加载properties文件

本案例将介绍如何加载properties文件,并将文件带入property的基本信息

我们大致将步骤分为以下三个步骤:

  • 开辟context命名空间:

<?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            "><!--以上beans的内容是,我们的命名空间开放过程只在原来的xml中: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            ">我们将添加以下内容:       xmlns:context="http://www.springframework.org/schema/context"并且在xsi:添加到schemalocation中:       http://www.springframework.org/schema/context       http://www.springframework.org/schema/context/spring-context.xsd(从以上内容整体复制,然后修改末尾xsi)--></beans>

  • 使用context命名空间加载指定的properties文件

<!--    2.使用context空间加载properties文件--><context:property-placeholder location="jdbc.properties"/>

  • 使用${}读取加载的属性值

<!--    3.使用属性占位符${}读取properties文件中的属性--><!--    说明:idea自动识别${}加载的属性值,需要手动点击才能查阅原始书写格式-->    <bean 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>

除上述基本操作外,我们在使用context命名空间时还需要注意很多点:

  • 不加载系统属性

<!--因为我们的系统属性优先>定义优先级,当我们的properties中的属性与系统设置的属性名相同时,Systemem可以优先匹配系统属性,导致错误-properties-设置mode--><context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/>

  • 加载多个properties文件

<!--我们可以用逗号或空间分隔加载多个properties文件--><context:property-placeholder location="jdbc.properties,jdbc2.properties" system-properties-mode="NEVER"/>

  • 加载所有properties文件

<!--我们可以用通配符设置加载文件,用*代替所有前缀,只保留properties的后缀--><context:property-placeholder location="*.properties" system-properties-mode="NEVER"/>

  • 标准格式加载properties

<!--我们通常用classpath来表示路径,以下形式更标准的classpath:*.properties  :   设置并加载当前工程路径中的所有properties文件--> <context:property-placeholder location="classpath:*.properties" system-properties-mode="NEVER"/>

  • 搜索从类路径或jar包中加载properties文件

<!--我们通常使用classpath*来表示路径来源classpath*:*.properties  :  在jar包中设置加载当前工程路径和当前工程所依赖的所有properties文件--><context:property-placeholder location="classpath*:*.properties" system-properties-mode="NEVER"/>

核心容器

bean和依赖注入的相关知识学习已经完成,接下来我们主要学习IOC容器中的核心容器。

这里提到的核心容器可以简单理解为ApplicationContext。接下来,我们将从以下问题入手,学习以下容器的相关知识:

  • 如何创建容器?
  • 创建容器后,如何从容器中获取bean对象?
  • 容器的层次结构是什么?
  • 什么是BeanFactory?
创建容器的方法

Aplicationcontext的创建方式为(XML配置文件在类路径下):

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

除此之外,Spring还提供了另一种创建方法(文件的绝对路径):

ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\workspace\\spring\\spring_10_container\\src\\main\\resources\\applicationContext.xml");

获取Bean的三种方式

方法一是在当前案例中获取的方法:

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

这种方法的问题是,每次获得时都需要转换类型

方式二:

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

这种方法可以解决类型强转问题,但增加了另一个参数,相对没有简化多少。

方式三:

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

这种方法类似于我们之前学到的依赖注入的类型注入。必须确保IOC容器中只有一个与此类型对应的bean对象。

容器层次结构

下面我们给出容器的层次图

一篇文章带你掌握主流基本框架——Spring_业务层_03

使用BeanFactory

用BeanFactory创建IOC容器的具体实现方法如下:

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();    }}

为了更好地看到BeanFactory和ApplicationContext之间的区别,在BookDaoimpl中添加以下结构函数:

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

如果不获得bean对象,打印会发现:

  • beanFactory是延迟加载,只有在获得bean对象时才会创建
  • Applicationcontext是立即加载的,容器加载时会创建bean对象
  • 如果Applicationcontext想要成为延迟加载,只需按以下方式进行配置
  • <?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" lazy-init="true"/> </beans>
总结核心概念

接下来,我们对以往知识进行总结,包括以下内容:

容器相关
  • BeanFactory是IoC容器的顶层接口,当BeanFactory对象初始化时,Bean延迟加载
  • Applicationcontext接口是Spring容器的核心接口,bean在初始化时立即加载
  • Applicationcontext接口提供基本的bean操作方法,并通过其他接口扩展其功能
  • Applicationcontext接口常用于初始ClaspathXmlaplicationcontext(常用)FileSystemXmlApplicationContext
bean相关

一篇文章带你掌握主流基础框架——Spring_spring_04

依赖注入相关

一篇文章带你掌握主流基础框架——Spring_业务层_05

注解开发

在上述开发中,xml配置文件的形式仍然有点复杂

此时,我们需要充分发挥Spring的优势:简化开发,通过注释简化开发过程

下面,我们将在多个方面逐步将Bean转化为注释

注释开发Bean

在之前的内容中,我们的bean在xml配置文件中组装

<?xml versinotallow="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.itheima.dao.impl.BookDaoImpl"/>    </beans>

在后期,我们的bean可以以注释的形式直接在实现类中注释

我们使用@component定义bean,可以添加参数来表示id,也可以不添加参数。后期我们使用class类型进行匹配

package com.itheima.dao.impl;import com.itheima.dao.BookDao;import org.springframework.stereotype.Component;import org.springframework.stereotype.Controller;import org.springframework.stereotype.Repository;//@Component定义beannt@Component("bookDao")public class BookDaoImpl implements BookDao {    public void save() {        System.out.println("book dao save ...");    }}

package com.itheima.service.impl;import com.itheima.dao.BookDao;import com.itheima.service.BookService;import org.springframework.stereotype.Component;import org.springframework.stereotype.Service;//@Component定义beannt@Componentpublic class BookServiceImpl implements BookService {    private BookDao bookDao;    public void setBookDao(BookDao bookDao) {        this.bookDao = bookDao;    }    public void save() {        System.out.println("book service save ...");        bookDao.save();    }}

@Componenty延伸了三种类型,在实现方法上是一致的,但可以用于各种类型(仅用于自我识别)

  • @Controller:用于定义表层bean
  • @Service:用于业务层bean定义
  • @Repository:用于定义数据层

package com.itheima.dao.impl;import com.itheima.dao.BookDao;import org.springframework.stereotype.Component;import org.springframework.stereotype.Controller;import org.springframework.stereotype.Repository;//@Component定义bean/////@Component("bookDao")//@Repository:@Component衍生注释@Repository("bookDao")public class BookDaoImpl implements BookDao {    public void save() {        System.out.println("book dao save ...");    }}

package com.itheima.service.impl;import com.itheima.dao.BookDao;import com.itheima.service.BookService;import org.springframework.stereotype.Component;import org.springframework.stereotype.Service;//@Component定义bean/////@Component//@Service:@Component衍生注释@Servicepublic class BookServiceImpl implements BookService {    private BookDao bookDao;    public void setBookDao(BookDao bookDao) {        this.bookDao = bookDao;    }    public void save() {        System.out.println("book service save ...");        bookDao.save();    }}

但是,在上述情况下,即使我们将@component类定义为beannt,

我们的xml文件无法检测到,因此我们需要配置相关的扫描组件来扫描bean

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:context="http://www.springframework.org/schema/context"       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        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">    <!--<context:component-scan />:扫描文件base-package:表示扫描路径-->        <context:component-scan base-package="com.itheima"/></beans>

纯注解开发

我们前面提到的注释开发属于2.5的附属版本

在Spring3.0版本中,Spring提供了纯注释开发模式,用java代替配置文件,开启了Spring快速开发时代

以前,我们的xml配置文件非常繁琐:

<!--本地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 id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>    </beans>

但是,我们可以通过创建单独的类来表示配置文件:

  • @Configuration:目前用于声明Spring配置类别
  • @ComponentScan:用于扫描文件(类似于<context:component-scan base-package="com.itheima"/>)

package com.itheima.config;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;//声明目前Spring配置类别@Configuration/设置bean扫描路径,多路径书写字符串数组格式@ComponentScan({"com.itheima.service","com.itheima.dao"})public class SpringConfig {}

注:由于这类属于配置类,我们通常单独列出一个文件夹来表示

常用文件夹:config

命名规范:SpringConfig,UserConfig...

由于我们的开发不再依赖于xml配置文件,Spring容器在主函数中的获取方式也发生了变化:

package com.itheima;import com.itheima.dao.BookDao;import com.itheima.service.BookService;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {    public static void main(String[] args) {                // 这是我们以前的获取方式,xml文件采用路径获取        // ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");                // 这是一种新的获取方式,直接提供配置类型        // Annotationconfigaplicationcontext加载Spring配置类初始Spring容器        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);                // 以后的操作不需要改变                BookDao bookDao = (BookDao) ctx.getBean("bookDao");        System.out.println(bookDao);        ///按类型获得bean        BookService bookService = ctx.getBean(BookService.class);        System.out.println(bookService);    }}

注释开发Bean的范围和管理

由于我们的Bean开发已经从xml转移到注释开发,一些配置设置也发生了变化

首先介绍Scope范围的设置方法:

  • @Scope:定义bean的作用范围

package com.itheima.dao.impl;import com.itheima.dao.BookDao;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Repository;import javax.annotation.PostConstruct;import javax.annotation.PreDestroy;@Repository///@Scope设置bean的作用范围(singleton或prototype),不添加默认singleton@Scope("singleton")public class BookDaoImpl implements BookDao {    public void save() {        System.out.println("book dao save ...");    }}

然后我们介绍一下bean生命周期的init和destroy操作:

  • @PostConstruct:定义init操作,表示构造后操作
  • @PreDestroy:定义destroy操作,表示销毁前操作
依靠注入(自动组装)

在Spring3.0中,省略了以前繁琐的依赖注入,我们的bean依赖注入只留下自动组装操作:

  • 使用@Autowired注释打开自动组装模式(按类型)
  • 当有相同类型时,我们使用@Qualifier打开按名自动组装

package com.itheima.service.impl;import com.itheima.dao.BookDao;import com.itheima.service.BookService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Service;@Servicepublic class BookServiceImpl implements BookService {    //@Autowired:注入引用类型,自动装配模式,默认按类型组装    @Autowired    //@Qualifier:bean自动组装时,按bean的名称组装    @Qualifier("bookDao")    private BookDao bookDao;    public void save() {        System.out.println("book service save ...");        bookDao.save();    }}

注:基于反射设计的自动组装创建对象,暴力反射对应属性为私有属性初始化数据,因此无需提供setter方法

注:建议使用无参结构方法创建对象(默认)。如果不提供相应的结构方法,请提供唯一的结构方法

注:@Qualifier是基于@Autowired实现的,必须保证Qualifier存在前有Autowired

除上述bean类型组装外,我们的简单类型组装仍然存在:

  • 我们以@Value的形式配置简单类型的值

package com.itheima.dao.impl;import com.itheima.dao.BookDao;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Repository;@Repository("bookDao")public class BookDaoImpl implements BookDao {    //@Value:注入简单类型(无需提供set方法)    @Value("123")    private String name;    public void save() {        System.out.println("book dao save ..." + name);    }}

之所以采用@Value的形式配置,是因为我们的类型值不一定是手动输入的,可能来自Properties资源:

  • 首先,我们需要在Springconfig中配置相关资源

package com.itheima.config;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;@Configuration@ComponentScan("com.itheima)//@PropertySource加载properties配置文件@PropertySource({"jdbc.properties"})public class SpringConfig {}

  • 然后,当我们在数据层调用时,我们使用${}来匹配数据

package com.itheima.dao.impl;import com.itheima.dao.BookDao;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Repository;@Repository("bookDao")public class BookDaoImpl implements BookDao {    //@Value:注入简单类型(无需提供set方法)    @Value("${name}")    private String name;    public void save() {        System.out.println("book dao save ..." + name);    }}

注释第三方beann的开发

在实际开发中,我们不仅需要管理自己的bean,有时还需要引进其他bean

让我们以Druid为例进行解释:

  1. 首先是pom.Druid坐标导入xml

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  <modelVersion>4.0.0</modelVersion>  <groupId>com.itheima</groupId>  <artifactId>spring_14_annotation_third_bean_manager</artifactId>  <version>1.0-SNAPSHOT</version>  <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></project>

  1. 第三方Bean使用@Bean配置

// 这个bean也属于config文件,我们也把它放在config文件夹中/// 后续我们将解释如何连接package com.itheima.config;import com.alibaba.druid.pool.DruidDataSource;import com.itheima.dao.BookDao;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import javax.sql.DataSource;public class JdbcConfig {        // 1.定义一种获得管理对象的方法        // 2.添加@Bean,表示当前方法的返回值是bean    // @Bean修饰方法,形状参根据类型自动组装    @Bean    public DataSource dataSource(){        DruidDataSource ds = new DruidDataSource();        ds.setDriverClassName("com.mysql.jdbc.Driver");        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");        ds.setUsername("root");        ds.setPassword("123456");        return ds;    }}

  1. 在核心配置(导入法)中加入独立配置类

// SpringConfigpackage com.itheima.config;import com.alibaba.druid.pool.DruidDataSource;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Import;import javax.sql.DataSource;@Configuration@ComponentScan("com.itheima")//@Import:导入配置信息(如果需要多个,也采用{}数组形式)@Import({JdbcConfig.class})public class SpringConfig {}

// JdbcConfigpackage com.itheima.config;import com.alibaba.druid.pool.DruidDataSource;import com.itheima.dao.BookDao;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import javax.sql.DataSource;//@Configurationpublic class JdbcConfig {    ///@Bean修改方法,形状参根据类型自动组装    @Bean    public DataSource dataSource(){        DruidDataSource ds = new DruidDataSource();// 配置信息        return ds;    }}

注:除上述介绍方法外,还有其他方法,但介绍方法属于主流,所以我们不介绍其他学校,感兴趣的学生可以咨询

注意第三方导入资源的开发

下面我们简单介绍一下我们的第三方bean也可能需要导入一些资源:

  • 依赖注入的简单类型

package com.itheima.config;import com.alibaba.druid.pool.DruidDataSource;import com.itheima.dao.BookDao;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import javax.sql.DataSource;//@Configurationpublic class JdbcConfig {        //1.定义获得管理对象的方法    @Value("com.mysql.jdbc.Driver")    private String driver;    @Value("jdbc:mysql://localhost:3306/spring_db")    private String url;    @Value("root")    private String userName;    @Value("root")    private String password;        //2.添加@Bean,表示当前方法的返回值是bean    ///@Bean修改方法,形状参根据类型自动组装    @Bean    public DataSource dataSource(){        DruidDataSource ds = new DruidDataSource();        ds.setDriverClassName(driver);        ds.setUrl(url);        ds.setUsername(userName);        ds.setPassword(password);        return ds;    }}

  • 依赖类型依赖注入

package com.itheima.config;import com.alibaba.druid.pool.DruidDataSource;import com.itheima.dao.BookDao;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import javax.sql.DataSource;public class JdbcConfig {    @Bean    public DataSource dataSource(BookDao bookDao){        // 我们只需要调用,该系统将自动为我们组装        System.out.println(bookDao);    }    }

引入类型注入只需为bean定义方法设置形参即可,容器将根据类型自动组装对象