spring框架学习
-
Spring是一个开源的、轻量级的容器(包含并管理对象的生命周期)框架
-
Spring是为了解决企业级开发中业务逻辑层中对象之间的耦合问题
-
Spring的核心是IOC和AOP
1. spring Bean
- Spring Bean是一个由Spring IOC容器实例化、组装和管理的对象。
- Java Bean是一个Java类:所有属性为private、提供默认构造方法、提供getter和setter、实现serializable接口。
- 对象就是普通的Java类实例化的产物,区别于上述Java bean的四点要求。
1.1 Spring bean的生命周期
BeanDefinition
Spring容器在进行实例化时,会将xml配置的的信息封装成一个BeanDefinition对象,Spring根据BeanDefinition来创建Bean对象,里面有很多的属性用来描述Bean。
1.2 spring框架中的单例bean不是线程安全的
Spring框架中有一个@Scope注解,默认的值就是singleton,单例的。因为一般在spring的bean的中都是注入无状态的对象,没有线程安
全问题,如果在bean中定义了可修改的成员变量,是要考虑线程安全问题的,可以使用多例或者加锁来解决
@Service
@Scope("singleton")
public class UserServiceImpl implements UserService{}
-
singleton:bean在每个Spring IOC中只有一个实例(单例)
-
prototype:一个bean的定义可以有多个实例
1.3 Sping中的循环依赖
循环依赖其实就是循环引用,在创建A对象的同时需要使用B对象,在创建B对象的也同时需要使用A对象,也就是两个或者两个以上的bean相互持有对方,最终形成闭环。
解决方法
使用Spring的三级缓存
缓存名称 | 源码名称 | 作用 |
---|---|---|
一级缓存 | singletonObjects | 单例池,缓存已经经历了完整的生命周期,已经初始化完成的bean对象 |
二级缓存 | earlySingletonObjects | 缓存早期的bean对象(生命周期还没有走完) |
三级缓存 | singletonFactories | 缓存的是ObjectFactory,表示对象工厂,用来创建某个对象的(可以解决创建代理对象的问题) |
注意:三个级别缓存需一起使用才能解决大部分循环依赖问题,若只有一级和二级不能解决代理对象循环依赖问题,若没有二级依赖则可能对导致多次调用工厂,可能会生成多例对象
若构造方法出现了循环依赖问题
由于bean的生命周期中构造函数是第一个执行的,spring框架的三级缓存并不能解决,因此我们需要在构造器中加入注解**@Lazy**,什么时候需要对象再进行bean对象的创建
public A(@Lazy B b){
System.out.println("A的构造方法执行");
this.b = b;
}
2. AOP(面向切面编程)
AOP用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取封装为一个可重用的模块,这个模块被命名为“ 切面 ”,减少系统中重复的代码,降低模块间的耦合度,同时提高系统的可维护性。
常见的AOP使用场景:核心是使用AOP的环绕通知+切点表达式(找到要记录日志的方法),通过环绕通知的参数获取请求方法的参数(类,方法,注解,请求方式等),获取到这些参数后,保存到数据库。
- 记录操作日志
- 处理缓存
- Spring中内置的事务处理(声明式事务管理:本质上是通过AOP功能,对方法进行拦截,在执行方法之前开启事务,执行完后根据执行情况提交或者回滚事务)
例:(通过AOP进行操作自动填充操作数据时间)
- 自定义一个注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCut {
String value();
}
- AOP进行管理的目标方法
// 新增菜品
@MyCut("save")//使用自定义的注解进行标识
@Insert("INSERT INTO dish(name, price, create_time) VALUES(#{name}, #{price}, #{createTime})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(Dish dish);
//自定义的切面类,在该类中实现操作方法
@Component
@Aspect //切面类
public class Aspect2 {
//设置切点,使用了自定义注解的方法进行AOP管理
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.aspect.MyCut)")
public void myPointCut() {
}
@Before("myPointCut()")
public void MyDoBefore(JoinPoint joinPoint) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
//判断是新增还是修改
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
MyCut annotation = signature.getMethod().getAnnotation(MyCut.class);
String value = annotation.value();//获取到操作类型
Object[] args = joinPoint.getArgs();//获取入参参数列表
if (args.length > 0) {
Object arg = args[0];//获取第一个参数(dish)
LocalDateTime now = LocalDateTime.now();//获取当前时间
if ("save".equals(value)) {
//通过反射来调用
Method setCreateTime = arg.getClass().getDeclaredMethod("setCreateTime", LocalDateTime.class);
Method setUpdateTime = arg.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
setCreateTime.invoke(arg, now);
setUpdateTime.invoke(arg, now);
} else if ("update".equals(value)) {
Method setUpdateTime = arg.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
setUpdateTime.invoke(arg, now);
}
}
}
}
3. Spring中事务失效
导致事务失效原因:
-
异常捕获处理
-
抛出检查异常
-
非public方法
4. SpringMVC的执行流程
-
视图阶段(老旧JSP等)
- 用户发送出请求到前端控制器DispatcherServlet
- DispatcherServlet收到请求调用HandlerMapping(处理器映射器)
- HandlerMapping找到具体的处理器,生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。
- DispatcherServlet调用HandlerAdapter(处理器适配器)
- HandlerAdapter经过适配调用具体的处理器(Handler/Controller)
- Controller执行完成返回ModelAndView对象
- HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet
- DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)
- ViewReslover解析后返回具体View(视图)
- DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)
- DispatcherServlet响应用户
-
前后端分离阶段(接口开发,异步)
- 用户发送出请求到前端控制器DispatcherServlet
- DispatcherServlet收到请求调用HandlerMapping(处理器映射器)
- HandlerMapping找到具体的处理器,生成处理器对象及处理器拦截器(如果有),再一起返
- 回给DispatcherServlet。
- DispatcherServlet调用HandlerAdapter(处理器适配器)
- HandlerAdapter经过适配调用具体的处理器(Handler/Controller)
- 方法上添加了@ResponseBody
- 通过HttpMessageConverter来返回结果转换为JSON并响应
5. Spring boot自动配置原理
-
在Spring Boot项目中的引导类上有一个注解**@SpringBootApplication**,这个注解是对三个注解进行了封装,分别是:
- @SpringBootConfiguration:该注解与@Configuration注解作用相同,用来声明当前是一个配置类
- @EnableAutoConfiguration:SpringBoot实现自动化配置的核心注解
- @ComponentScan:组件扫描,默认扫描当前引导类所在包及其子包
-
其中**@EnableAutoConfiguration是实现自动化配置的核心注解。该注解通过@lmport注解导入对应的配置选择器。内部就是读取了该项目和该项目引用的Jar包的的classpath路径下META-INF/spring.factories**文件中的所配置的类的全类名。在这些配置类中所定义的Bean会根据条件注解所指定的条件来决定是否需要将其导入到Spring容器中。
-
条件判断会有像**@ConditionalOnClass**这样的注解,判断是否有对应的class文件,如果有则加载该类,把这个配置类的所有的Bean
放入spring容器中使用。
@SpringBootApplication
public class JixiOrderSystemApplication {
public static void main(String[] args) {
SpringApplication.run(JixiOrderSystemApplication.class, args);
}
}
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
6.Spring 框架中常用注解
6.1 spring 常见注解
注解 | 说明 |
---|---|
@Component、@Controller、@Service、@Repository | 使用在类上用于实例化Bean |
@Autowired | 使用在字段上用于根据类型依赖注入 |
@Qualifier | 结合@Autowired一起使用用于根据名称进行依赖注入 |
@Resource | @Autowired + @Qualifier |
@Scope | 标准Bean的作用范围 |
@Configuration | 指定当前是一个spring配置类,当创建容器时会从该类上加载注解 |
@ComponentScan | 用于指定spring初始化容器时要扫描的包 |
@Bean | 使用在方法上,标注将该方法的返回值存储到spring容器中 |
@Import | 使用@Import导入的类会被spring加载到IOC容器中 |
@Aspect、@Before、@After、@Around、@Pointcut | 用于切面编程(aop) |
6.2 SpringMVC常见的注解
注解 | 说明 |
---|---|
@RequesMapping | 用于映射请求路径,可以定义在类上和方法上。用于类上,则表示类中的所有方法都是以该地址作为父路径 |
@RequestBody | 注解实现接收http请求的json数据,将json转换为java对象 |
@RequestParam | 指定请求参数的名称 |
@PathViriable | 从请求路径中获取请求参数(/user/{id}),传递给方法的形式参数 |
@RequestBody | 注解实现将controller方法返回对象转换为json对象响应给客户端 |
@RequestHeader | 获取指定的请求头数据 |
@RestController | @Controller+@RequeseBody |
6.3 SpringBoot常见注解
注解 | 说明 |
---|---|
@SpringBootApplication | springBoot核心注解;组合注解,包含 @Configuration 、@EnableAutoConfiguration 和 @ComponentScan ;用于标识 Spring Boot 应用的主类; |
@SpringBootConfiguration | 组合了-@Configuration注解,实现配置文件的功能 |
@EnableAutoConfiguration | 打开自动配置的功能,也可以关闭某个自动配置的选项 |
@ComponentScan | Spring组件扫描 |
主播还在学习ing
| @SpringBootConfiguration | 组合了-@Configuration注解,实现配置文件的功能 |
| @EnableAutoConfiguration | 打开自动配置的功能,也可以关闭某个自动配置的选项 |
| @ComponentScan | Spring组件扫描 |
主播还在学习ing