为避免白学告警这种情况的发生,只上重点,只上干货
首先介绍一下SSM框架,以避免认识不清晰的情况发生
ssm中讲的是spring framework
介绍一下架构:
(1)核心层
Core Container:核心容器,这个模块是Spring最核心的模块,其他的都需要依赖该模块
(2)AOP层
AOP:面向切面编程,它依赖核心层容器,目的是在不改变原有代码的前提下对其进行功能增强
Aspects:AOP是思想,Aspects是对AOP思想的具体实现
(3)数据层
Data Access:数据访问,Spring全家桶中有对数据访问的具体实现技术
Data Integration:数据集成,Spring支持整合其他的数据层解决方案,比如Mybatis
Transactions:事务,Spring中事务管理是Spring AOP的一个具体实现
(4)Web层
(5)Test层
Spring主要整合了Junit来完成单元测试和集成测试
对Spring的学习主要包含四部分内容:
为解决耦合度较高的问题,Spring提出了一个解决方案:
使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象
这也就是Spring的核心思想
首先,这几个概念要是很清楚就直接往下拉看案例
控制反转,使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转,简单点说,就是创建对象的控制权,被反转到了Spring框架上。
控制反转英文全称:Inversion of Control。控制反转通过依赖注入(DI)方式实现对象之间的松耦合关系。程序运行时,依赖对象由辅助程序动态生成并注入到被依赖对象中,动态绑定两者的使用关系。Spring IoC 容器就是这样的辅助程序,它负责对象的生成和依赖的注入,然后再交由我们使用。
IoC容器:具有依赖注入功能的容器,可以创建对象的容器。IoC容器负责实例化、定位、配置应用程序中的对象并建立这些对象之间的依赖。
它可以装载bean,也是一种降低对象之间耦合关系的设计思想。(比如租房子。以前租房子需要一个房子一个房子找,费时费力,然后现在加入一个房屋中介,把你需要的房型告诉中介,就可以直接选到需要的房子,中介就相当于spring容器。)
- Bean是被实例的、组装的、及被Spring容器管理的Java对象。
- Spring容器会自动完成Bean对象的实例化。
- 创建应用对象之间的协作关系的行为被称为:装配,这就是依赖注入的本质。
补充一下Dao层和Service层的概念:
Service是业务层,Dao是数据访问层,这样的分层是基于MVC架构来说的。Dao层:全称为data access object,属于一种比较底层,比较基础的操作,具体到对于某个表、某个实体的增删改查
Service层:被称为服务,肯定是相比之下比较高层次的一层结构,相当于将几种操作封装起来。
具体起来,Dao的作用是封装对数据库的访问:增删改查,不涉及业务逻辑,只是达到按某个条件获得指定数据的要求;
而Service,则是专注业务逻辑,对于其中需要的数据库操作,都通过Dao去实现。简单来说就是Dao层是底层,具体到某一张表的增删查改,可以理解为有多少张表就有多少个Dao层,而Service成可以理解为是Dao层的
“上司”,通过Service层来控制Dao层。一个Service层控制一个或者多个Dao层。
入门案例的思路:
步骤1:
导入Spring坐标
<!-- 定义项目的依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<!-- 配置依赖的groupId,表示所依赖的模块或组件的唯一ID -->
<artifactId>spring-context</artifactId>
<!-- 配置依赖的artifactId,表示所依赖的模块或组件的名称 -->
<version>5.2.10.RELEASE</version>
<!-- 配置依赖的版本号 -->
</dependency>
博主用的是:IntelliJ IDEA 2022.2.3 (Ultimate Edition),是会有警告的,这里不用管,因为5.2.10.RELEASE是最稳定的目前
步骤2:
定义Spring管理的类(接口)
public interface BookDao {
public void save();
}
public interface BookService {
public void save();
}
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;
}
}
步骤3:
创建Spring配置文件,配置对应类作为Spring管理的bean
bean定义时id属性在同一个上下文中不能重复
步骤4:
初始化IoC容器(Spring核心容器/Spring容器),通过容器获取bean
public class App {
public static void main(String[] args) {
BookService bookService = new BookServiceImpl();
bookService.save();
}
}
在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入
业务层要用数据层的类对象,以前是自己 new 的,现在自己不new了,靠 别人[外部其实指的就是IOC容器] 来给注入进来,这种思想就是依赖注入
这个需要程序员根据业务需求提前建立好关系,如业务层需要依赖数据层,service就要和dao建立依赖关系
介绍完Spring的IOC和DI的概念后,我们会发现这两个概念的最终目标就是:充分解耦
具体实现靠:
案例思想:
具体实现:
步骤1:
删除使用new的形式创建对象的代码
public class BookServiceImpl implements BookService {
//5.删除业务层中使用new的方式创建的dao对象
private BookDao bookDao;
public void save() {
bookDao.save();
}
}
步骤2:
提供依赖对象对应的setter方法
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
步骤3:
配置service与dao之间的关系
ref对应的是bean的名称
name对应的是属性的名称
下面详细讲解这三个内容
bean的语法:
<bean id="" class="">
这张表包括bean标签的功能,使用方式,id和class属性的作用
这里就简单带过
在spring的配置文件中,给name配置多个值
<!--name:为bean指定别名,别名可以有多个,使用逗号,分号,空格进行分隔-->
<bean id="bookService" name="service service4 bookEbi" class="com.itheima.service.impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"/>
</bean>
bean的作用范围:
bean的作用范围由scope属性决定
scope取singleton时bean为单例,scope取prototype时bean为非单例
之所以bean默认为单例,是因为在Spring的IOC容器中只会有该类的一个对象
bean对象只有一个就避免了对象的频繁创建与销毁,达到了bean对象的复用,性能高
适合交给容器进行管理的bean的scope设置为singleton
不适合交给容器进行管理的bean的scope设置为prototype
实例化bean有三种方法
首先是无参的构造方法实例化对象,比较常用
//提供可访问的构造方法
public class BookDaoImpl implements BookDao{
public void save(){
System.out.println("...")
}
}
配置
<bean
id="bookDao"
class="..."
/>
补充一下什么是工厂
工厂模式是属于创建型模式的,通过工厂获取一个一个的新对象。说白了,工厂就是用来 new(创建)对象的,因此把它化分到创建型这一类中。
这里就说一下简单工厂
简单地说,简单工厂模式通常就是这样,一个工厂类 XxxFactory,里面有一个静态方法,根据我们不同的参数,返回不同的派生自同一个父类(或实现同一接口)的实例对象。
我们强调职责单一原则,一个类只提供一种功能,例如FoodFactory 的功能就是只要负责生产各种 Food。
第二个方法:使用静态工厂实例化bean
这里了解即可
建议先构建一个这样的结构
在spring配置文件中
<bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>
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();
}
}
方法三:实例化工厂(了解)
方法2,3都是针对早期遗留问题
<!--方式三:使用实例工厂实例化bean-->
<bean id="userFactory" class="com.itheima.factory.UserDaoFactory"/>
<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
方法四:使用FactoryBean实例化(重点)
1.创建一个UserDaoFactoryBean的类,实现FactoryBean接口,重写接口的方法
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
//实现FactoryBean接口,此处代表工厂生产产品的类型为UserDao
//代替原始实例工厂中创建对象的方法
public UserDao getObject() throws Exception {
//通过定义的工厂方法获取产品实例
return new UserDaoImpl();
//实例化一个实现了UserDao接口的实现类对象
}
public Class<?> getObjectType() {
//获取工厂生产的产品类型
return UserDao.class;
//返回工厂创建的产品类型
}
}
2.在Spring的配置文件中进行配置
<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>
3.AppForInstanceUser运行类不用做任何修改,直接运行
public class AppForInstanceUser {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//验证单例
UserDao userDao1 = (UserDao) ctx.getBean("userDao");
UserDao userDao2 = (UserDao) ctx.getBean("userDao");
System.out.println(userDao1);
System.out.println(userDao2);
// userDao.save();
}
}
这里可能出现这种报错:java: 错误: 不支持发行版本 5
这里在pom.xml文件下的project标签下复制以下代码
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
source和target按照你自己的版本来
这种方式在Spring去整合其他框架的时候会被用到
查看源码会发现,FactoryBean接口其实会有三个方法,分别是:
总结: 目前只会用到构造方法,要重点掌握
对于bean的生命周期控制在bean的整个生命周期中所处的位置如下:
Spring提供了两个接口来完成生命周期的控制,好处是可以不用再进行配置 init-method 和 destroy-method
在BookServiceImpl完成这两个接口的使用:
修改BookServiceImpl类,添加两个接口 InitializingBean , DisposableBean 并实现接口中的两个方法 afterPropertiesSet 和 destroy
// 定义一个BookServiceImpl类,实现BookService接口,并且同时实现了InitializingBean和DisposableBean接口
public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
private BookDao bookDao; // 声明一个私有的BookDao类型的实例变量
// 定义一个set方法,用于依赖注入书籍数据访问对象
public void setBookDao(BookDao bookDao) {
System.out.println("set .....");
this.bookDao = bookDao;
}
// 定义一个保存方法,用于保存书籍信息
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
// 实现DisposableBean接口的方法之一,当bean销毁时调用
public void destroy() throws Exception {
System.out.println("service destroy");
}
// 实现InitializingBean接口的方法之一,当bean初始化完成后调用
public void afterPropertiesSet() throws Exception {
System.out.println("service init");
}
}
需注意细节:
关闭容器
暴力方法:close方法
ApplicationContext中没有close方法
需要将ApplicationContext更换成ClassPathXmlApplicationContext
ClassPathXmlApplicationContext ctx = new
ClassPathXmlApplicationContext("applicationContext.xml");
调用ctx的close()方法
//关闭容器
ctx.close();
注册钩子关闭容器
在容器未关闭之前,提前设置好回调函数,让JVM在退出之前回调此函数来关闭容器
调用ctx的registerShutdownHook()方法
ctx.registerShutdownHook();
不同点:
close()是在调用的时候关闭,registerShutdownHook()是在JVM退出前调用关闭。
补充:什么是jvm?
(1)jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的。
(2)jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和一个存储方法域。
(3)JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。
DI (Dependency Injection):依赖注入是指在 Spring IOC 容器创建对象的过程中,将所依赖的对象通过配置进行注入。我们可以通过依赖注入的方式来降低对象间的耦合度。
setter注入:
1)创建学生类Student
package com.mkbk.spring.pojo;
public class Student implements Person{
private Integer sid;
private String sname;
private Integer age;
private String gender;
public Student(Integer sid, String sname, Integer age, String gender) {
this.sid = sid;
this.sname = sname;
this.age = age;
this.gender = gender;
}
public Student() {
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", sname='" + sname + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
2)配置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 id="studentOne" class="com.mkbk.spring.pojo.Student" scope="singleton"></bean>
<bean id="studentTwo" class="com.mkbk.spring.pojo.Student" scope="singleton">
<property name="sid" value="1001"></property>
<property name="sname" value="1001"></property>
<property name="age" value="23"></property>
<property name="gender" value="男"></property>
</bean>
</beans>
3)测试
public class IOCByXMLTest {
public void testDI(){
ApplicationContext ioc=new ClassPathXmlApplicationContext("Application.xml");
// Student student=ioc.getBean("studentTwo",student.class);
}
public void testIOC(){
ApplicationContext ioc=new ClassPathXmlApplicationContext("ApplicationContext.xml");
// Student studentOne=(Student) ioc.getBean("studentOne");
// Student student=ioc.getBean(Student.class);
Student studentOne=ioc.getBean("studentOne",Student.class);
System.out.println(studentOne);
}
}
构造器注入
1)在Student类中添加有参构造
public Student(Integer id, String name, Integer age, String sex) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
2)配置bean
<bean id="studentTwo" class="com.atguigu.spring.bean.Student">
<constructor-arg value="1002"></constructor-arg>
<constructor-arg value="李四"></constructor-arg>
<constructor-arg value="33"></constructor-arg>
<constructor-arg value="女"></constructor-arg>
</bean>
3)测试
@Test
public void testDIBySet(){
ApplicationContext ac = new ClassPathXmlApplicationContext("spring-di.xml");
Student studentOne = ac.getBean("studentTwo", Student.class);
System.out.println(studentOne);
}
分割线-----------------------------------------------------------------更新中…