一 简介
-
什么是Spring:轻量级的 DI / IoC 和 AOP 容器的开源框架
-
有啥好处:
-
管理创建和组装对象之间的依赖关系 使用前:手工创建
-
-
面向切面编程(AOP)可以解耦核心业务和边缘业务的关系
场景:用户调用下单购买视频接口,需要判断登录,拦截器是AOP思想的一种实现
使用前:代码写逻辑,每次下单都调用方法判断,多个方法需要判断登录则都需要 登录方法判断
使用后:根据一定的方法或者路径规则进行判断是否要调用,降低代码耦合度
-
包含java大型项目里面常见解决方案 web层、业务层、数据访问层等
-
极其便利的整合其他主流技术栈,比如redis、mq、mybatis、jpa
-
社区庞大和活跃,在微服务、大数据、云计算都有对应的组件
二 使用 IDEA + Maven + Spring5创建项目
-
创建项目
- maven
-
添加依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.5.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.2.5.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>5.2.5.RELEASE</version> </dependency>
添加配置文件applicationContext.xml
-
添加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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean name="video" class="net.xdclass.sp.domain.Video" scope="prototype"> <property name="name" value="tom"/> <property name="id" value="23"/> </bean> </beans>
三 applicationContext.xml配置文件
bean标签 id属性:指定Bean的名称,在Bean被别的类依赖时使用
name属性:用于指定Bean的别名,如果没有id,也可以用name
class属性:用于指定Bean的来源,要创建的Bean的class类,需要全限定名
四 spring的IOC设计思想
-
什么是IOC Inverse of Control(控制反转)是一种设计思想 将原本在程序中手动创建对象的流程,交由Spring框架来管理 核心:把创建对象的控制权反转给Spring框架,对象的生命周期由Spring统一管理
把spring ioc 当成一个容器,里面存储管理的对象称为Bean,类实例
-
案例实操 配置文件里面定义一个bean,通过代码去获取
<bean name="video" class="net.xdclass.sp.domain.Video"> <property name="id" value="9"/> <property name="title" value="Spring 5.X课程" /> </bean> ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); Video video = (Video)applicationContext.getBean("video"); System.out.println(video.getTitle());
五 讲解spring的依赖注入讲解
-
什么是DI Dependency Injection ,依赖注入
IOC容器在运行期间,动态地将对象某种依赖关系注入到对象之中,比如视频订单对象,依赖用视频对象
<bean id="video" class="net.xdclass.sp.domain.Video"> <property name="id" value="9"/> <property name="title" value="Spring 5.X课程" /> </bean> <bean id="videoOrder" class="net.xdclass.sp.domain.VideoOrder" > <property name="id" value="8" /> <property name="outTradeNo" value="23432fnfwedwefqwef2"/> <property name="video" ref="video"/> </bean>
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Video video = (Video)context.getBean("video"); System.out.println(video.getTitle()); VideoOrder videoOrder = (VideoOrder) context.getBean("videoOrder"); System.out.println(videoOrder.getOutTradeNo()); System.out.println(videoOrder.getVideo().getTitle());
六 spring的bean 属性scope作用域
scope属性
- singleton:单例, 默认值,调用getBean方法返回是同一个对象,实例会被缓存起来,效率比较高 当一个bean被标识为singleton时候,spring的IOC容器中只会存在一个该bean
<!--<bean id="video" class="net.xdclass.sp.domain.Video" scope="singleton"> -->
<bean id="video" class="net.xdclass.sp.domain.Video" scope="prototype">
<property name="id" value="9"/>
<property name="title" value="Spring 5.X课程" />
</bean>
-
prototype: 多例,调用getBean方法创建不同的对象,会频繁的创建和销毁对象造成很大的开销
-
其他少用 (作用域 只在 WebApplicationContext)
- request :每个Http请求都会创建一个新的bean
- session: 每个Http Session请求都会创建一个新的bean
- global session(基本不用)
private static void testScope(ApplicationContext context){
Video video1 = (Video)context.getBean("video");
Video video2 = (Video)context.getBean("video");
//靠匹配内存地址,== 是匹配内存地址
System.out.println( video1 == video2 );
}
七 Spring5.X常见的注入方式
- 使用set方法注入
<bean id="video" class="net.xdclass.sp.domain.Video" scope="singleton"> <property name="id" value="9"/> <property name="title" value="Spring 5.X课程" /> </bean>
- 使用带参的构造函数注入
<bean id="video" class="net.xdclass.sp.domain.Video" > <constructor-arg name="title" value="面试专题课程第一季"></constructor-arg> </bean>
- POJO类型注入(property 没有使用value属性,而是使用了ref属性)
<bean id="video" class="net.xdclass.sp.domain.Video" > <constructor-arg name="title" value="面试专题课程第一季"></constructor-arg> </bean> <bean id="videoOrder" class="net.xdclass.sp.domain.VideoOrder" > <property name="id" value="8" /> <property name="outTradeNo" value="23432fnfwedwefqwef2"/> <property name="video" ref="video"/> </bean>
- 注意: 类的构造函数重写的时候,一定要保留空构造函数!!!
八 List-Map类型的注入
<bean id="video" class="net.xdclass.sp.domain.Video" >
<!--list类型注入-->
<property name="chapterList">
<list>
<value>第一章SpringBoot</value>
<value>第二章Mybatis</value>
<value>第三章Spring</value>
</list>
</property>
<property name="videoMap">
<map>
<entry key="1" value="SpringCloud课程"></entry>
<entry key="2" value="面试课程"></entry>
<entry key="3" value="javaweb课程"></entry>
</map>
</property>
</bean>
public class Video {
private int id;
private String title;
private List<String> chapterList;
private Map<Integer,String> videoMap;
//省略set get方法
}
九 spring里面bean的依赖和继承
- bean继承:两个类之间大多数的属性都相同,避免重复配置,通过bean标签的parent属性重用已有的Bean元素的配置信息 继承指的是配置信息的复用,和Java类的继承没有关系
<bean id="video" class="net.xdclass.sp.domain.Video" scope="singleton"> <property name="id" value="9"/> <property name="title" value="Spring 5.X课程" /> </bean> <bean id="video2" class="net.xdclass.sp.domain.Video2" scope="singleton" parent="video"> <property name="summary" value="这个是summary"></property> </bean>
- 属性依赖: 如果类A是作为类B的属性, 想要类A比类B先实例化,设置两个Bean的依赖关系
<bean id="video" class="net.xdclass.sp.domain.Video" scope="singleton"> <property name="id" value="9"/> <property name="title" value="Spring 5.X课程" /> </bean> <!--设置两个bean的关系,video要先于videoOrder实例化--> <bean id="videoOrder" class="net.xdclass.sp.domain.VideoOrder" depends-on="video"> <property name="id" value="8" /> <property name="outTradeNo" value="23432fnfwedwefqwef2"/> <property name="video" ref="video"/> </bean>
十 spring里面bean的生命周期里面的init和destroy方法
<bean id="video" class="net.xdclass.sp.domain.Video" scope="singleton" init-method="init" destroy-method="destroy"> <property name="id" value="9"/> <property name="title" value="Spring 5.X课程" /> </bean> public static void main(String [] args){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); ((ClassPathXmlApplicationContext) context).registerShutdownHook(); }
十一 Spring的BeanPostProcessor使用
-
什么是BeanPostProcessor
- 是Spring IOC容器给我们提供的一个扩展接口
- 在调用初始化方法前后对 Bean 进行额外加工,ApplicationContext 会自动扫描实现了BeanPostProcessor的 bean,并注册这些 bean 为后置处理器
- 是Bean的统一前置后置处理而不是基于某一个bean
- 执行顺序
Spring IOC容器实例化Bean 调用BeanPostProcessor的postProcessBeforeInitialization方法 调用bean实例的初始化方法 调用BeanPostProcessor的postProcessAfterInitialization方法
-
注意:接口重写的两个方法不能返回null,如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bean实例对象
public class CustomBeanPostProcessor implements BeanPostProcessor,Ordered { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("CustomBeanPostProcessor1 postProcessBeforeInitialization beanName="+beanName); return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("CustomBeanPostProcessor1 postProcessAfterInitialization beanName="+beanName); return bean; } public int getOrder() { return 1; } }
-
可以注册多个BeanPostProcessor顺序
- 在Spring机制中可以指定后置处理器调用顺序,通过BeanPostProcessor接口实现类实现Ordered接口getOrder方法,该方法返回整数,默认值为 0优先级最高,值越大优先级越低
十二 Spring的Bean的自动装配属性autowire
-
属性注入
- 前面学过属性注入,set方法、构造函数等,属于手工注入
- 有没办法实现自动装配注入?
-
Spring自动注入
-
使用元素的 autowire 属性为一个 bean 定义指定自动装配模式
-
autowire设置值
-
no:没开启
-
byName: 根据bean的id名称,注入到对应的属性里面
-
byType:根据bean需要注入的类型,注入到对应的属性里面
- 如果按照类型注入,存在2个以上bean的话会抛异常
- expected single matching bean but found 2
-
constructor: 通过构造函数注入,需要这个类型的构造函数
-
-
<!--<bean id="videoOrder" class="net.xdclass.sp.domain.VideoOrder" autowire="byName">--> <!--<bean id="videoOrder" class="net.xdclass.sp.domain.VideoOrder" autowire="byType">--> <bean id="videoOrder" class="net.xdclass.sp.domain.VideoOrder" autowire="constructor"> <property name="id" value="8" /> <property name="outTradeNo" value="23432fnfwedwefqwef2"/> </bean>
-