目录
service接口实现类:在service中调用mapper
2.2.2创建spring容器,使用@ComponentScan("需要扫描进ioc容器的类路径")将组件交给spring容器进行统一管理
加入@Component即可将该类扫描进IOC容器,当需要该类对象时,只需加入@Autowired注解注入即可
1. Spring框架概述
1.1 为什么要学习Spring
Spring技术是JavaEE开发必备技能,企业开发技术选型命中率远大于90%。
特点:1,简化开发,降低企业级开发复杂性。2,框架整合,例如Mybatis、Mybatis-plus、Struts、Struts2、Hibernate,提高企业级应用开发与运行效率。3,节约成本,让代码量更小
spring 发展历程,spring framework--> spring boot--> spring cloud,要想学习spring boot单体架构和spring cloud微服务架构,需要先学习spring framework
1.2 Spring两大核心思想
IOC(控制反转):从原来的主动new对象,到从ioc容器中获取对象,而具体实现是通过DI依赖注入的方式,此过程中对象创建控制权由程序转移到外部,此思想叫做控制反转;DI依赖注入,指的是将一个对象包装成一个bean,在容器中建立bean与bean之间依赖关系的整个过程,称为依赖注入
AOP(面向切面编程):OOP为面向对象编程,AOP为面向切面编程,一种编程范式,指导开发者如何组织程序结构,作用是在不惊动原设计的基础上进行功能增强,对应Spring理念为无侵入式,原理是动态代理(通过反射的方式进行获取),应用在日志、异常捕获和处理、监控统计代码、记录过程,例如数据库触发器就是通过此思想实现的
2.spring基础入门
2.1回顾servlet
service接口实现类:在service中调用mapper
mapper接口实现类:
启动类:
可发现会有很多new对象的过程,俗话说new是万恶之源,使得代码中每一层级内容较为耦合,严重会导致牵一发而动全身的效果,也就是屎山!!!
2.2spring入门案例1(IOC)
2.2.1导入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.12</version>
</dependency>
⚠️:若使用5版本,未来的springboot版本只能是2.3、2.5、2.7,2开头,若是3版本则对应spring版本必须是6.0.6以上
2.2.2创建spring容器,使用@ComponentScan("需要扫描进ioc容器的类路径")将组件交给spring容器进行统一管理
package com.itgaohe.config;
import org.springframework.context.annotation.ComponentScan;
/**
* @Classname SpringConfig
* @Description
* @Date 2025/5/4 21:59
* @Created by 孟祥宇
*/
//config:configuration 配置
//spring容器自动扫描com.itgaohe文件下所有文件夹下所有组件(加了component注解的类)
@ComponentScan("com.itgaohe")
public class SpringConfig {
}
加入@Component即可将该类扫描进IOC容器,当需要该类对象时,只需加入@Autowired注解注入即可
package com.itgaohe.service.impl;
import com.itgaohe.mapper.UserMapper;
import com.itgaohe.mapper.impl.UserMapperImpl;
import com.itgaohe.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @Classname UserServiceImpl
* @Description
* @Date 2025/5/4 21:19
* @Created by 孟祥宇
*/
//声明此类为一个bean 就有可能将这个bean交给spring容器做统一管理
@Component
public class UserServiceImpl implements UserService {
// DI依赖注入
@Autowired
private UserMapper userMapper;
@Override
public void selectAll() {
System.out.println("userService selectAll run ...");
userMapper.selectAll();
}
}
package com.itgaohe.mapper.impl;
import com.itgaohe.mapper.UserMapper;
import org.springframework.stereotype.Component;
/**
* @Classname UserMapperImpl
* @Description
* @Date 2025/5/4 21:20
* @Created by 孟祥宇
*/
@Component
public class UserMapperImpl implements UserMapper {
@Override
public void selectAll() {
System.out.println("userMapper selectAll run ...");
}
}
2.2.3由spring容器进行调用
package com.itgaohe;
import com.itgaohe.config.SpringConfig;
import com.itgaohe.service.UserService;
import com.itgaohe.service.impl.UserServiceImpl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @Classname App
* @Description
* @Date 2025/5/4 21:23
* @Created by 孟祥宇
*/
public class App {
public static void main(String[] args) {
// UserServiceImpl userService = new UserServiceImpl();
// userService.selectAll();
// 获取ioc容器
AnnotationConfigApplicationContext ioc
= new AnnotationConfigApplicationContext(SpringConfig.class);
// 根据类型获取bean
UserService bean = ioc.getBean(UserService.class);
// 根据名称获取bean只需在注入到IOC容器中的类名上通过@Component("beanName")方式即可,getbean("beanName")
bean.selectAll();
}
}
2.2.4延申依赖
被扫描注解@Conponent--未知bean(常见于工厂、导入的其他项目模块)
@Controller--控制层
@Service--业务层
@Repository/@Mapper--持久层
依赖注入@Autowired--注入引用类型,自动装配模式,默认按类型装配
@Qualifier("bean名称")--自动装配bean时按bean名称装配(⚠️:Qualifier必须和Autowired配合使用不可单独使用!!!)
2.2.5bean的生命周期
生命周期可以帮助我们进行一些初始化到销毁的备份等操作
<!-- 生命周期注解依赖 -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
package com.itgaohe.pojo;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
* @Classname Student
* @Description
* @Date 2025/5/5 16:31
* @Created by 孟祥宇
*/
@Component
public class Student {
private String name;
public Student(){
System.out.println("1.Student无参构造方法");
}
public void setName(String name) {
this.name = name;
System.out.println("2.set赋值");
}
// 初始化注解
@PostConstruct
public void init(){
System.out.println("3.init初始化");
}
public String getName() {
System.out.println("4.get方法");
return name;
}
// IOC关闭bean销毁的注解
@PreDestroy
public void destroy(){
System.err.println("5.销毁");
}
}
package com.itgaohe;
import com.itgaohe.config.SpringConfig;
import com.itgaohe.pojo.Student;
import com.itgaohe.service.UserService;
import com.itgaohe.service.impl.UserServiceImpl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @Classname App
* @Description
* @Date 2025/5/4 21:23
* @Created by 孟祥宇
*/
public class App {
public static void main(String[] args) {
// UserServiceImpl userService = new UserServiceImpl();
// userService.selectAll();
// 获取ioc容器
AnnotationConfigApplicationContext ioc
= new AnnotationConfigApplicationContext(SpringConfig.class);
// 根据名称获取
// UserService bean = ioc.getBean(UserService.class);
//
// bean.selectAll();
Student bean = ioc.getBean(Student.class);
// ioc容器关闭
ioc.close();
}
}
此过程展示了从IOC容器获取对象,到IOC容器关闭时对象被销毁的过程,但一般项目开发中@Component不会在pojo实体类中使用,此代码为方便展示bean的生命周期,故加了扫描进IOC容器的注解
2.3spring入门案例2(AOP)
2.2.1概念概述
1.连接点(JoinPoint):正在执行的方法,例如:update(),delete(),select()等都是连接点。
2.切入点(Pointcut):进行功能增强了的方法,例如update(),delete()方法select()方法没有被增强所以不是切入点,但是连接点。在springAOP中,一个切入点可以指一个方法也可以匹配多个方法,一个具体方法:com.xxxx.dao包下的BookDao接口中的无形参无返回值的save方法,匹配多个方法:所有的save方法,所有以get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法
3.通知(Advice):在切入点前后执行的操作,也就是增强的共性功能,在springAOP中功能最终以方法的方式呈现
4.通知类:通知方法所在的类叫做通知类
5.切面(Aspect):描述通知与切入点的对应关系,也就是哪些通知方法对应哪些切入点方法。
2.2.2AOP实现方式
1.导入依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
2.新建切面类,并放于advice包下,先加@Component注解将切面类注入到IOC容器,再用@Aspect注解声明此类为切面类,制作空方法pt()用@Pointcut注解通过权限定名和该类下的selectAll()方法做连接,使用@Before和@After注解来指代注解后的方法在pt()前或后执行
package com.itgaohe.advice;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @Classname UserAdvice
* @Description
* @Date 2025/5/6 15:03
* @Created by 孟祥宇
*/
//1.将切面类注入到IOC容器
@Component
//2.声明此类为切面类
@Aspect
public class UserAdvice {
// 制作切入点,通过全限定名来找到具体方法,此时com.itgaohe.service包下的UserService类中的selectAll()方法即为连接点
@Pointcut("execution(public void com.itgaohe.service.UserService.selectAll())")
public void pt(){}
@Before(value = "pt()")
public void adivceDemo(){
System.out.println("执行前操作...");
}
@After(value = "pt()")
public void adviceDemo1(){
System.out.println("日志输出after...");
}
}
@Around环绕通知,在这个例子中,通过环绕通知,我们不仅可以在目标方法执行前后输出信息,还可以计算目标方法的执行时间。
package com.itgaohe.advice;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @Classname UserAdvice
* @Description
* @Date 2025/5/6 15:03
* @Created by 孟祥宇
*/
//1.将切面类注入到IOC容器
@Component
//2.声明此类为切面类
@Aspect
public class UserAdvice {
// 制作切入点,通过全限定名来找到具体方法,此时com.itgaohe.service包下的UserService类中的selectAll()方法即为连接点
@Pointcut("execution(public void com.itgaohe.service.UserService.selectAll())")
public void pt(){}
// @Before(value = "pt()")
// public void adivceDemo(){
// System.out.println("执行前操作...");
// }
// @After(value = "pt()")
// public void adviceDemo1(){
// System.out.println("日志输出after...");
// }
@Around("pt()")
public void adviceDemo2(ProceedingJoinPoint joinPoint) {
long startTime = System.currentTimeMillis();
try {
System.out.println("环绕通知 - 执行前操作...");
joinPoint.proceed(); // 执行目标方法
System.out.println("环绕通知 - 执行后操作...");
} catch (Throwable e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("方法执行耗时:" + (endTime - startTime) + " 毫秒");
}
}
总结:以上即为对Spring框架基础入门的介绍,重在两大核心思想的具体实现方法,即IOC和AOP,bean的声明周期(非重点),只需在面试前背一下即可