您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

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

时间:2022-11-03 11:40:00  来源:网易号  作者:嘻呱互联

这篇文章中我们将会介绍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 Framework:Spring框架
  • Spring Boot:Spring简化代码开发
  • Spring Cloud:Spring分布设计
Spring FrameWork系统架构

 

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

 

  • Spring FrameWork是Spring生态圈中最基本的项目,是其他项目的根基

 


 

我们现在所使用的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 工厂。
核心概念介绍

 

首先我们思索一下我们之前的业务层与数据层:

// 数据层接口 public interface BookDao { public void save(); }// 数据层实现 public class BookDaoImpl implements BookDao { public void save() { System.out.println("book dao save ..."); } }// 业务层接口 public interface BookService { public void save(); }// 业务层实现 public 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提供了一个容器,被称为Ioc容器,用来充当IoC思想的外部
  • IoC容器负责对象的创建,初始化等一系列工作,被创建和管理的对象在IoC容器中被称为Bean
// 数据层实现 public class BookDaoImpl implements BookDao { public void save() { System.out.println("book dao save ..."); } }// IoC容器 /* 包含 dao service 两者可以建立连接 */// 业务层实现 public class BookServiceImpl implements BookService { private BookDao bookDao; public void save() { bookDao.save(); } }

 

目的:充分解耦

 

  • IoC:使用IoC容器管理bean
  • DI:在IoC容器内将有依赖关系的bean进行关系绑定

 

最终效果:

 

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

 

首先我们需要明白IoC的使用规则:

 

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

 

下面我们给出IoC入门的详细步骤:

 

  1. 创建Maven项目,在pom.xml中导入坐标
org.springframework spring-context 5.2.10.RELEASE
  1. 创建Spring.xml的配置包(applicationContext.xml,导入坐标后xml中更新该XML)
  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. 基于IoC管理bean
  2. Service中使用new形式创建Dao对象是否保留:(否)
  3. Service中需要Dao对象如何进入到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的连接
Bean整体介绍

 

Bean是保存在IoC中的对象,我们通过配置的方式获得Bean

下面我们从三个方面分别讲解Bean:

bean基本配置

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

类别

描述

名称

bean

类型

所属

beans标签

功能

定义Spring核心容器管理对象

格式

属性列表

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

范例

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

类别

描述

名称

name

类型

所属

bean标签

功能

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

范例

 

正常情况下,使用id和name都可以获得bean,但推荐还是使用唯一id 获得bean无论通过id还是name获取,如果无法找到则抛出异常NosuchBeanDefinitionException

 

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

类别

描述

名称

scope

类型

所属

bean标签

功能

定义bean的作用范围,可选范围如下:
singleton:单列(默认)
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 ..."); } }

若无参构造方法不存在,则抛出异常BeanCreationException
  1. 静态工厂(了解)

 

我们在之前的案例中存在有对象工厂的说法,我们可以设置工厂并调用其方法得到bean

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

  1. 实例工厂(了解)

 

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

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

  1. FactoryBean(重要实用)

 

除了我们之前自己定义的工厂外,Spring提供了一种官方版本的FactoryBean

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

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

我们需要提及一下bean的销毁时机:(了解即可)

 

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

 

所以如果我们希望销毁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 ) { // 注意:这里需要采用ClassPathXmlApplicationContext作为对象,因为只有这个类才具有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属性注入简单类型数据

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属性注入引用类型数据

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

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

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

配置中使用constructor-arg标签value属性注入简单类型数据

根据构造方法参数名称注入构造器注入引用类型(了解)

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

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

配置中使用constructor-arg标签ref属性注入简单类型数据

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

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

但如果我们在bean中的数据名称发生改变,配置就不再适配,所以提供了一些方法来解决参数配置问题:

 

  • 配置中使用constructor-arg标签type属性设置按形参类型注入
根据构造方法参数类型注入
  • 配置中使用constructor-arg标签index属性设置按形参类型注入
依赖注入方式选择

 

依赖注入方式有以下选择标准:

 

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

 

在前面我们学习了手动注入的方法,但Spring其实为我们提供了一种依赖自动装配的语法:

 

  • IoC容器根据bean所依赖的资源在容器中自动查找并注入bean中的过程称为自动装配

 

自动装配方式:

 

  • 按类型(常用)
  • 按名称
  • 按构造方法
  • 不启用

 

自动装配语法:

 

依赖自动装配特征: 自动装配用于引用类型注入,不能对简单类型进行操作使用按类型装配时(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 list; private Set set; private Map map; private Properties properties; public void setArray(int[] array) { this.array = array; } public void setList(List list) { this.list = list; } public void setSet(Set set) { this.set = set; } public void setMap(Map 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); } }100 200 300 itcast itheima boxuegu chuanzhihui itcast itheima boxuegu boxuegu china henan kaifeng案例:数据源对象管理

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

 

  • 导入druid坐标
4.0.0 com.itheima spring_09_datasource 1.0-SNAPSHOT org.springframework spring-context 5.2.10.RELEASE com.alibaba druid 1.1.16 MySQL mysql-connector-java 5.1.47
  • 配置数据源对象作为Spring管理的bean
案例:加载properties文件

 

这个案例我们将会介绍如何加载properties文件,并将文件带入到property基本信息中

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

 

  • 开辟context命名空间:
  • 使用context命名空间,加载指定properties文件
  • 使用${}读取加载的属性值

 

除了上述的基本操作,我们在context命名空间的使用中有很多需要注意的点:

 

  • 不加载系统属性
  • 加载多个properties文件
  • 加载所有properties文件
  • 加载properties文件标准格式
  • 从类路径或jar包中搜索并加载properties文件
核心容器

 

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

这里所说的核心容器,大家可以把它简单的理解为ApplicationContext,接下来我们从以下几个问题入手来学习下容器的相关知识:

 

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

 

案例中创建ApplicationContext的方式为(类路径下的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对象只能有一个。

容器类层次结构

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


 

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要想成为延迟加载,只需要按照如下方式进行配置
  •  
核心概念总结

 

接下来我们对前面知识的一个总结,共包含如下内容:

容器相关

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

 


 

依赖注入相关


 

注解开发

在上述的开发中,我们采用xml配置文件的形式来说依旧显得有些复杂

这时我们就需要发挥Spring的优点:简化开发,通过注解来简化开发过程

下面我们会通过多个方面将Bean逐步转化为注解

注解开发Bean

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

在后期,我们的bean可以采用注解的形式,直接在实现类中注解表示为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定义bean @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定义bean @Component public 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衍生注解 @Service public 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的类定义为bean

我们的xml文件是无法探测到的,所以我们需要配置相关扫描组件来扫描bean

纯注解开发

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

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

在之前我们的xml配置文件是很繁琐的:

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

 

  • @Configuration:用于声明当前类为Spring配置类
  • @ComponentScan:用于扫描类文件(类似于)
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"); // 这是新的获取方式,直接提供配置类的类型 // AnnotationConfigApplicationContext加载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; @Service public 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实现的,必须保证先有Autowired才能存在Qualifier

 

除了上述的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); } }注解开发第三方bean

 

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

下面我们以Druid为例进行讲解:

 

  1. 首先在pom.xml中导入Druid坐标
4.0.0 com.itheima spring_14_annotation_third_bean_manager 1.0-SNAPSHOT org.springframework spring-context 5.2.10.RELEASE com.alibaba druid 1.1.16
  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. 将独立的配置类加入核心配置(导入法)
// SpringConfig package 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 { }// JdbcConfig 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; //@Configuration public 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; //@Configuration public 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定义方法设置形参即可,容器会根据类型自动装配对象
原文链接:https://www.cnblogs.com/qiuluoyuweiliang/p/16750470.html


Tags:Spring   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Spring Security:保障应用安全的利器
SpringSecurity作为一个功能强大的安全框架,为Java应用程序提供了全面的安全保障,包括认证、授权、防护和集成等方面。本文将介绍SpringSecurity在这些方面的特性和优势,以及它...【详细内容】
2024-02-27  Search: Spring  点击:(55)  评论:(0)  加入收藏
Spring Security权限控制框架使用指南
在常用的后台管理系统中,通常都会有访问权限控制的需求,用于限制不同人员对于接口的访问能力,如果用户不具备指定的权限,则不能访问某些接口。本文将用 waynboot-mall 项目举例...【详细内容】
2024-02-19  Search: Spring  点击:(39)  评论:(0)  加入收藏
详解基于SpringBoot的WebSocket应用开发
在现代Web应用中,实时交互和数据推送的需求日益增长。WebSocket协议作为一种全双工通信协议,允许服务端与客户端之间建立持久性的连接,实现实时、双向的数据传输,极大地提升了用...【详细内容】
2024-01-30  Search: Spring  点击:(19)  评论:(0)  加入收藏
Spring实现Kafka重试Topic,真的太香了
概述Kafka的强大功能之一是每个分区都有一个Consumer的偏移值。该偏移值是消费者将读取的下一条消息的值。可以自动或手动增加该值。如果我们由于错误而无法处理消息并想重...【详细内容】
2024-01-26  Search: Spring  点击:(88)  评论:(0)  加入收藏
SpringBoot如何实现缓存预热?
缓存预热是指在 Spring Boot 项目启动时,预先将数据加载到缓存系统(如 Redis)中的一种机制。那么问题来了,在 Spring Boot 项目启动之后,在什么时候?在哪里可以将数据加载到缓存系...【详细内容】
2024-01-19  Search: Spring  点击:(86)  评论:(0)  加入收藏
Spring Boot2.0深度实践 核心原理拆解+源码分析
Spring Boot2.0深度实践:核心原理拆解与源码分析一、引言Spring Boot是一个基于Java的轻量级框架,它简化了Spring应用程序的创建过程,使得开发者能够快速搭建一个可运行的应用...【详细内容】
2024-01-15  Search: Spring  点击:(96)  评论:(0)  加入收藏
SpringBoot3+Vue3 开发高并发秒杀抢购系统
开发高并发秒杀抢购系统:使用SpringBoot3+Vue3的实践之旅随着互联网技术的发展,电商行业对秒杀抢购系统的需求越来越高。为了满足这种高并发、高流量的场景,我们决定使用Spring...【详细内容】
2024-01-14  Search: Spring  点击:(91)  评论:(0)  加入收藏
Spring Boot 3.0是什么?
Spring Boot 3.0是一款基于Java的开源框架,用于简化Spring应用程序的构建和开发过程。与之前的版本相比,Spring Boot 3.0在多个方面进行了改进和增强,使其更加易用、高效和灵活...【详细内容】
2024-01-11  Search: Spring  点击:(133)  评论:(0)  加入收藏
GraalVM与Spring Boot 3.0:加速应用性能的完美融合
在2023年,SpringBoot3.0的发布标志着Spring框架对GraalVM的全面支持,这一支持是对Spring技术栈的重要补充。GraalVM是一个高性能的多语言虚拟机,它提供了Ahead-of-Time(AOT)编...【详细内容】
2024-01-11  Search: Spring  点击:(124)  评论:(0)  加入收藏
Spring Boot虚拟线程的性能还不如Webflux?
早上看到一篇关于Spring Boot虚拟线程和Webflux性能对比的文章,觉得还不错。内容较长,抓重点给大家介绍一下这篇文章的核心内容,方便大家快速阅读。测试场景作者采用了一个尽可...【详细内容】
2024-01-10  Search: Spring  点击:(119)  评论:(0)  加入收藏
▌简易百科推荐
Qt与Flutter:在跨平台UI框架中哪个更受欢迎?
在跨平台UI框架领域,Qt和Flutter是两个备受瞩目的选择。它们各自具有独特的优势,也各自有着广泛的应用场景。本文将对Qt和Flutter进行详细的比较,以探讨在跨平台UI框架中哪个更...【详细内容】
2024-04-12  刘长伟    Tags:UI框架   点击:(1)  评论:(0)  加入收藏
Web Components实践:如何搭建一个框架无关的AI组件库
一、让人又爱又恨的Web ComponentsWeb Components是一种用于构建可重用的Web元素的技术。它允许开发者创建自定义的HTML元素,这些元素可以在不同的Web应用程序中重复使用,并且...【详细内容】
2024-04-03  京东云开发者    Tags:Web Components   点击:(8)  评论:(0)  加入收藏
Kubernetes 集群 CPU 使用率只有 13% :这下大家该知道如何省钱了
作者 | THE STACK译者 | 刘雅梦策划 | Tina根据 CAST AI 对 4000 个 Kubernetes 集群的分析,Kubernetes 集群通常只使用 13% 的 CPU 和平均 20% 的内存,这表明存在严重的过度...【详细内容】
2024-03-08  InfoQ    Tags:Kubernetes   点击:(19)  评论:(0)  加入收藏
Spring Security:保障应用安全的利器
SpringSecurity作为一个功能强大的安全框架,为Java应用程序提供了全面的安全保障,包括认证、授权、防护和集成等方面。本文将介绍SpringSecurity在这些方面的特性和优势,以及它...【详细内容】
2024-02-27  风舞凋零叶    Tags:Spring Security   点击:(55)  评论:(0)  加入收藏
五大跨平台桌面应用开发框架:Electron、Tauri、Flutter等
一、什么是跨平台桌面应用开发框架跨平台桌面应用开发框架是一种工具或框架,它允许开发者使用一种统一的代码库或语言来创建能够在多个操作系统上运行的桌面应用程序。传统上...【详细内容】
2024-02-26  贝格前端工场    Tags:框架   点击:(47)  评论:(0)  加入收藏
Spring Security权限控制框架使用指南
在常用的后台管理系统中,通常都会有访问权限控制的需求,用于限制不同人员对于接口的访问能力,如果用户不具备指定的权限,则不能访问某些接口。本文将用 waynboot-mall 项目举例...【详细内容】
2024-02-19  程序员wayn  微信公众号  Tags:Spring   点击:(39)  评论:(0)  加入收藏
开发者的Kubernetes懒人指南
你可以将本文作为开发者快速了解 Kubernetes 的指南。从基础知识到更高级的主题,如 Helm Chart,以及所有这些如何影响你作为开发者。译自Kubernetes for Lazy Developers。作...【详细内容】
2024-02-01  云云众生s  微信公众号  Tags:Kubernetes   点击:(51)  评论:(0)  加入收藏
链世界:一种简单而有效的人类行为Agent模型强化学习框架
强化学习是一种机器学习的方法,它通过让智能体(Agent)与环境交互,从而学习如何选择最优的行动来最大化累积的奖励。强化学习在许多领域都有广泛的应用,例如游戏、机器人、自动驾...【详细内容】
2024-01-30  大噬元兽  微信公众号  Tags:框架   点击:(68)  评论:(0)  加入收藏
Spring实现Kafka重试Topic,真的太香了
概述Kafka的强大功能之一是每个分区都有一个Consumer的偏移值。该偏移值是消费者将读取的下一条消息的值。可以自动或手动增加该值。如果我们由于错误而无法处理消息并想重...【详细内容】
2024-01-26  HELLO程序员  微信公众号  Tags:Spring   点击:(88)  评论:(0)  加入收藏
SpringBoot如何实现缓存预热?
缓存预热是指在 Spring Boot 项目启动时,预先将数据加载到缓存系统(如 Redis)中的一种机制。那么问题来了,在 Spring Boot 项目启动之后,在什么时候?在哪里可以将数据加载到缓存系...【详细内容】
2024-01-19   Java中文社群  微信公众号  Tags:SpringBoot   点击:(86)  评论:(0)  加入收藏
站内最新
站内热门
站内头条