Spring简介

一、Spring简介

1 Spring介绍

  • ==简化开发==,降低企业级开发的复杂性

  • ==框架整合==,高效整合其他技术,提高企业级应用开发与运行效率

1.2 spring的作用
  • 简化开发

  • ==IOC(反转控制)==

  • ==AOP(面向切面编程)==

  • ==事务处理==

  • 框架整合

  • MyBatis

  • MyBatis-plus

  • Struts

  • Struts2

  • Hibernate

  • ……

2 初识Spring

2.1 Spring家族
  • Spring发展到今天已经形成了一种开发的生态圈,Spring提供了若干个项目,每个项目用于完成特定的功能。

3 Spring体系结构

3.1 Spring Framework系统架构图
  • Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基

4 Spring核心概念

4.1 目前我们代码存在的问题
  • 代码书写现状

  • 耦合度偏高

  • 解决方案

  • 使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象

4.2 核心概念
  • ==IOC(Inversion of Control)控制反转==

使用对象时,由主动new产生对象转换为由==外部==提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转。通俗的讲就是“==将new对象的权利交给Spring,我们从Spring中获取对象使用即可==”

  • Spring技术对IoC思想进行了实现

  • Spring提供了一个容器,称为==IOC容器==,用来充当IoC思想中的“外部”

  • IOC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为==Bean==

  • ==DI(Dependency Injection)依赖注入==

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

  • 目标:充分解耦

  • 使用IoC容器管理bean(IOC)

  • 在IoC容器内将有依赖关系的bean进行关系绑定(DI)

  • 最终效果

  • 使用对象时不仅可以直接从IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系

二、IOC和DI入门案例

1 IOC入门案例

1.1 门案例思路分析
  1. 管理什么?(Service与Dao)

  1. 如何将被管理的对象告知IOC容器?(配置文件)

  1. 被管理的对象交给IOC容器,如何获取到IoC容器?(接口)

  1. IOC容器得到后,如何从容器中获取bean?(接口方法)

  1. 使用Spring导入哪些坐标?(pom.xml)

1.2 实现步骤

【第一步】导入Spring坐标

【第二步】定义Spring管理的类(接口)

【第三步】创建Spring配置文件,配置对应类作为Spring管理的bean对象

【第四步】初始化IOC容器(Spring核心容器/Spring容器),通过容器获取bean对象

1.3 实现代码

【第一步】导入Spring坐标

<dependencies>

<!--导入spring的坐标spring-context,对应版本是5.2.10.RELEASE-->

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context</artifactId>

<version>5.2.10.RELEASE</version>

</dependency>

</dependencies>

【第二步】定义Spring管理的类(接口)

  • BookDao接口和BookDaoImpl实现类

publicinterfaceOrderDao {

publicvoidsave();

}

publicclassOrderDaoImplimplementsOrderDao {

publicvoidsave() {

System.out.println("order dao save ...");

}

}

  • BookService接口和BookServiceImpl实现类

publicinterfaceOrderService {

publicvoidsave();

}

publicclassOrderServiceImplimplementsBookService {

privateOrderDaoorderkDao=newOrderDaoImpl();

publicvoidsave() {

System.out.println("order service save ...");

orderDao.save();

}

}

【第三步】创建Spring配置文件,配置对应类作为Spring管理的bean对象

  • 定义applicationContext.xml配置文件并配置BookServiceImpl

<?xmlversion="1.0" encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans " target="_blank">http://www.springframework.org/schema/beans/spring-beans.xsd">

<!--

bean标签:表示配置bean

id属性:表示给bean起名字

class属性:表示给bean定义类型

-->

<beanid="orderService"class="com.by.service.impl.OrderServiceImpl"></bean>

</beans>

==注意事项:bean定义时id属性在同一个上下文中(IOC容器中)不能重复==

【第四步】初始化IOC容器(Spring核心容器/Spring容器),通过容器获取Bean对象

publicclassApp {

publicstaticvoidmain(String[] args) {

//1.创建IoC容器对象,加载spring核心配置文件

ApplicationContextctx=newClassPathXmlApplicationContext("applicationContext.xml");

//2 从IOC容器中获取Bean对象(BookService对象)

OrderServiceorderService= (BookService)ctx.getBean("orderService");

//3 调用Bean对象(BookService对象)的方法

orderService.save();

}

}

1.4 运行结果

1.5spring相关API

1.5.1 ApplicationContext的继承体系

applicationContext:接口类型,代表应用上下文,可以通过其实例获得 Spring 容器中的 Bean 对象

1.5.2 ApplicationContext的实现类

1)ClassPathXmlApplicationContext

它是从类的根路径下加载配置文件 推荐使用这种

2)FileSystemXmlApplicationContext

它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。

3)AnnotationConfigApplicationContext

当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。

1.5.3 getBean()方法使用

publicObjectgetBean(Stringname) throwsBeansException {

assertBeanFactoryActive();

returngetBeanFactory().getBean(name);

}

public<T>TgetBean(Class<T>requiredType) throwsBeansException { assertBeanFactoryActive();

returngetBeanFactory().getBean(requiredType);

}

其中,当参数的数据类型是字符串时,表示根据Bean的id从容器中获得Bean实例,返回是Object,需要强转。

当参数的数据类型是Class类型时,表示根据类型从容器中匹配Bean实例,当容器中相同类型的Bean有多个时,则此方法会报错

getBean()方法使用

ApplicationContextapplicationContext=new

ClassPathXmlApplicationContext("applicationContext.xml");

UserServiceuserService1= (UserService) applicationContext.getBean("userService");

UserServiceuserService2=applicationContext.getBean(UserService.class);

2 DI入门案例

2.1 DI入门案例思路分析
  1. 基于IOC管理bean

  1. Service中使用new形式创建的Dao对象是否保留?(否)

  1. Service中需要的Dao对象如何进入到Service中?(提供方法)

  1. Service与Dao间的关系如何描述?(配置)

2.2 实现步骤

【第一步】删除使用new的形式创建对象的代码

【第二步】提供依赖对象对应的setter方法

【第三步】配置service与dao之间的关系

2.3 实现代码

【第一步】删除使用new的形式创建对象的代码

public class OrderServiceImpl implements OrderService {

//引入dao对象

private OrderDao orderDao ; //【第一步】删除使用new的形式创建对象的代码

@Override

public void add() {

System.out.println("order service save ...");

orderDao.save();

}

}

【第二步】提供依赖对象对应的setter方法

public class OrderServiceImpl implements OrderService {

//引入dao对象

private OrderDao orderDao ;

public void setOrderDao(OrderDao orderDao) {

this.orderDao = orderDao;

}

@Override

public void add() {

System.out.println("order service save ...");

orderDao.save();

}

}

【第三步】配置service与dao之间的关系

在applicationContext.xml中配置

<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 " target="_blank">http://www.springframework.org/schema/beans/spring-beans.xsd">

<!--

bean标签:表示配置bean

id属性:表示给bean起名字

class属性:表示给bean定义类型

-->

<bean id="orderDao" class="com.by.dao.impl.OrderDaoImpl"></bean>

<bean id="orderService" class="com.by.service.impl.OrderServiceImpl">

<!--配置service和dao的关系

property标签,表示配置当前bean的属性

name属性:指代引用哪一个属性

ref属性:表示参照哪一个id

-->

<property name="orderDao" ref="orderDao"/>

</bean>

</beans>

三、Bean的基础配置

1 Bean基础配置

代码演示
<bean id="orderDao" class="com.by.dao.impl.OrderDaoImpl"></bean>
<bean id="orderService" class="com.by.service.impl.OrderServiceImpl">

2 Bean别名配置

配置说明

类型

描述

名称

name

类型

属性

所属

bean标签

功能

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

范例

3 Bean作用范围配置

配置说明

类型

描述

名称

scope

类型

属性

所属

bean标签

功能

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

范例

扩展:scope的取值不仅仅只有singleton和prototype,还有request、session、application、 websocket ,表示创建出的对象放置在web容器(tomcat)对应的位置。比如:request表示保存到request域中。
代码演示

<!-- sope 是bean的作用范围 可选单例singleton 非单例prototype-->

<bean id="bookDao" class="com.by.dao.impl.BookDaoImpl" scope="singleton"></bean>

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

@Test

public void springdemo01(){

//演示单例 非单例

ApplicationContext ac=new ClassPathXmlApplicationContext("application.xml");

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

BookDao bookDao2=(BookDao)ac.getBean("bookDao");

System.out.println(bookDao);

System.out.println(bookDao2);

}

最后给大家说明一下:在我们的实际开发当中,绝大部分的Bean是单例的,也就是说绝大部分Bean不需要配置scope属性。

四、Bean的实例化

2 实例化Bean的三种方式

2.1 构造方法方式
  • BookDaoImpl实现类

public class BookDaoImpl implements BookDao {

public BookDaoImpl() {

System.out.println("book dao 构造运行中。。。。");

}

@Override

public void save() {

System.out.println("book dao save....");

}

}

  • applicationContext.xml配置

<!--方式一:构造方法实例化bean-->

<bean id="bookDao" class="com.by.dao.impl.BookDaoImpl"/>

  • AppForInstanceBook测试类

public class AppForInstanceBook {

public static void main(String[] args) {

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

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

bookDao.save();

}

}

  • 运行结果

==注意:无参构造方法如果不存在,将抛出异常BeanCreationException==

2.2 静态工厂方式
  • OrderDao接口和OrderDaoImpl实现类

public interface OrderDao {

public void save();

}

public class OrderDaoImpl implements OrderDao {

public void save() {

System.out.println("order dao save ...");

}

}

  • OrderDaoFactory工厂类

//静态工厂创建对象

public class OrderDaoFactory {

public static OrderDao getOrderDao(){

System.out.println("工厂类创建中。。。");

return new OrderDaoImpl();

}

}

  • applicationContext.xml配置

<!--方式二:使用静态工厂实例化bean-->

<bean id="orderDao" class="com.by.factory.OrderDaoFactory" factory-method="getOrderDao"/>

  • AppForInstanceOrder测试类

public class AppForInstanceOrder {

public static void main(String[] args) {

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

OrderDao orderDao = (OrderDao) ctx.getBean("orderDao");

orderDao.save();

}

}

  • 运行结果

2.3 实例工厂方式
  • UserDao接口和UserDaoImpl实现类

public interface UserDao {

public void save();

}

public class UserDaoImpl implements UserDao {

public void save() {

System.out.println("user dao save ...");

}

}

  • UserDaoFactory工厂类

//实例工厂创建对象

public class UserDaoFactory {

public UserDao getUserDao(){

return new UserDaoImpl();

}

}

  • applicationContext.xml配置

<!--方式三:使用实例工厂实例化bean-->

<bean id="userFactoy" class="com.by.factory.UserDaoFactory"/>

<bean id="userDao" factory-method="getUserDao" factory-bean="userFactoy"/>

  • AppForInstanceUser测试类

public class AppForInstanceUser {

public static void main(String[] args) {

// //创建实例工厂对象

// UserDaoFactory userDaoFactory = new UserDaoFactory();

// //通过实例工厂对象创建对象

// UserDao userDao = userDaoFactory.getUserDao();

// userDao.save();

ApplicationContext ac=new ClassPathXmlApplicationContext("application.xml");

UserDao userDao = (UserDao)ac.getBean("userDao");

userDao.save();

}

}

  • 运行结果

2.4 实现FactoryBean<T>方式【扩展,了解】
  • 定义UserDaoFactoryBean实现FactoryBean<UserDao>

UserDaoFactoryBean中实例化什么类型的对象泛型就是该类型。

//FactoryBean创建对象

public class UserDaoFactoryBean implements FactoryBean<UserDao> {

//代替原始实例工厂中创建对象的方法

public UserDao getObject() throws Exception {

return new UserDaoImpl();

}

public Class<?> getObjectType() {

return UserDao.class;

}

}

  • applicationContext.xml配置

<!--方式四:使用FactoryBean实例化bean-->

<bean id="userDao" class="com.by.factory.UserDaoFactoryBean"/>

使用之前的AppForInstanceUser测试类去运行看结果就行了。注意配置文件中id="userDao"是否重复。

五、Bean的生命周期

1 生命周期相关概念介绍

  • 生命周期:从创建到消亡的完整过程

  • bean生命周期:bean从创建到销毁的整体过程

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

2 代码演示

2.1 Bean生命周期控制
  • 提供生命周期控制方法

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

}

}

  • applicationContext.xml配置

<!--init-method:设置bean初始化生命周期回调函数,此处填写init方法名-->

<!--destroy-method:设置bean销毁生命周期回调函数,仅适用于单例对象,此处填写destory方法名-->

<bean id="bookDao" class="com.by.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>

  • 测试类

public class AppForLifeCycle {

public static void main( String[] args ) {

//此处需要使用实现类类型,接口类型没有close方法

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

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

bookDao.save();

//关闭容器,执行销毁的方法

ctx.close();

}

}

2.2 Bean生命周期控制
  • 实现InitializingBean, DisposableBean接口

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

}

}

applicationContext.xml配置:

<bean id="bookDao" class="com.by.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"></bean>

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

<property name="bookDao" ref="bookDao"></property>

</bean>

3 Bean销毁时机

  • 容器关闭前触发bean的销毁

  • 关闭容器方式:

  • 手工关闭容器ConfigurableApplicationContext接口close()操作

  • 注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机ConfigurableApplicationContext接口registerShutdownHook()操作

public class AppForLifeCycle {

public static void main( String[] args ) {

//此处需要使用实现类类型,接口类型没有close方法

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

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

bookDao.save();

//注册关闭钩子函数,在虚拟机退出之前回调此函数,关闭容器

ctx.registerShutdownHook();

//关闭容器

//ctx.close();

}

}

六、依赖注入(DI配置)

1 依赖注入方式

1.1 依赖注入的两种方式
  • setter注入简单类型==引用类型(很常用)==

  • 构造器注入简单类型引用类型

1.2 setter方式注入
1.3 构造方式注入

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

public class OrderServiceImpl implements OrderService {

//引入dao对象

private OrderDao orderDao ;

public OrderServiceImpl(OrderDao orderDao) {

this.orderDao = orderDao;

}

配置中使用constructor-arg标签 ref属性注入引用类型对象

<bean id="orderDao" class="com.by.dao.impl.OrderDaoImpl"></bean>

<bean id="orderService" class="com.by.service.impl.OrderServiceImpl">

<constructor-arg name="orderDao" ref="orderDao"/>

</bean>

1.4 依赖注入方式选择
  1. 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现

  1. 可选依赖使用setter注入进行,灵活性强

  1. Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨

  1. 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入

  1. 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入

  1. ==自己开发的模块推荐使用setter注入==

2 依赖自动装配

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

  • 自动装配方式==按类型(常用)==按名称按构造方法不启用自动装配

2.2 自动装配类型
依赖自动装配
配置中使用bean标签autowire属性设置自动装配的类型---按类型

<bean id="bookDao" class="com.by.dao.impl.BookDaoImpl"/>

<bean id="bookService" class="com.by.service.impl.BookServiceImpl" autowire="byType"/>

代码演示:

public class BookDaoImpl implements BookDao {

@Override

public void save() {

System.out.println("book dao save ...");

}

serviceImpl:

public class BookServiceImpl implements BookService {

private BookDao bookDao;

public void setBookDao(BookDao bookDao) {

this.bookDao = bookDao;

}

@Override

public void save() {

bookDao.save();

System.out.println("book dao running.....");

}

测试:

ApplicationContext ac=new ClassPathXmlApplicationContext("application.xml");

BookService bookService= (BookService) ac.getBean("bookService");

bookService.save();

问题导入:

如果出现两个id怎么办?比如

<bean id="bookDao" class="com.by.dao.impl.BookDaoImpl"/>

<bean id="bookDao2" class="com.by.dao.impl.BookDaoImpl"/>

<bean id="bookService" class="com.by.service.impl.BookServiceImpl" autowire="byType" />

依赖自动装配特征
  1. 自动装配用于引用类型依赖注入,不能对简单类型进行操作

  1. 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用

  1. 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用

  1. 自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效

3 集合注入

准备工作:

public class OrderDaoImpl implements OrderDao {

public int[] array;

public List<String> list;

public Set<String> set;

public Map<String,String> map;

public Properties properties;

//生成Setter方法

3.1 注入数组类型数据

<bean id="orderDao" class="com.by.dao.impl.OrderDaoImpl">

<property name="array">

<array>

<value>100</value>

<value>200</value>

<value>300</value>

</array>

</property>

</bean>

3.2 注入List类型数据

<property name="list">

<list>

<value>xx</value>

<value>xx</value>

<value>xx</value>

<value>xx</value>

</list>

</property>

3.3 注入Set类型数据

<property name="set">

<set>

<value>xx</value>

<value>xx</value>

<value>xx</value>

<value>xx</value>

</set>

</property>

3.4 注入Map类型数据

<property name="map">

<map>

<entry key="country" value="china"/>

<entry key="province" value="henan"/>

<entry key="city" value="kaifeng"/>

</map>

</property>

3.5 注入Properties类型数据

<property name="properties">

<props>

<prop key="country">china</prop>

<prop key="province">henan</prop>

<prop key="city">kaifeng</prop>

</props>

</property>

说明:property标签表示setter方式注入,构造方式注入constructor-arg标签内部也可以写<array>、<list>、<set>、<map>、<props>标签
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值