spring基础
对spring的理解
spring如何管理Bean(核心思想:依赖注入)
注册Bean
- 注册
Bean: 相当于new一个java类—–独立抽出依赖 - 常用注释:
@Bean、@Component、@Controller、@Service、@Repository
装配Bean
- 装配
Bean: 相当于调用new得到的java类,来使用它;按类型装配由于Java多态性实现IOC—–注入依赖 - 常用注解:
@Autowired
理解
注册过的Bean会存放在spring容器中,当装配Bean时,会从spring容器中(按类型、按名字)去取出适合的Bean new成实例,提供使用。
而按类型装配Bean,则会灵活的利用java多态性,实现IOC。
MVC思想
Controller控制器
- 返回体定制:
ResponseEntity
常用注释
spring内置常用注释列表
项目主入口注解
@SpringBootApplication
相当于以下三个注解:
-
@EnableAutoConfiguration: 启用Spring Boot的自动配置机制;所以在Spring Boot中以下@EnableXXX可写可不写:a. 包括了:
@EnableAspectJAutoProxy;容器中注册的Bean可以使用AOP
这样被注册的Bean,就可以使用@Aspect、@Pointcut、@Around等实现AOP了。
[为什么spring boot直接可以使用AOP](java – Spring AOP works without @EnableAspectJAutoProxy? – Stack Overflow)b. 包括了:
@EnableWebMvc:容器中注册的Bean可以使用成为拦截器
这样被注册的Bean,就可以使用implements WebMvcConfigurer注入拦截器了c. 包括了:
@EnableAsync:容器中注册的Bean可以使用异步多线程这样被注册的
Bean,就可以使用@Async执行异步函数了d. 包括了:
@EnableScheduling:容器中注册的Bean可以使用定时任务这样被注册的
Bean,就可以使用@Scheduled执行定时任务函数了e. 包括了:
@EnableTransactionManagement:容器中注册的Bean可以使用事务这样被注册的
Bean,就可以使用@Transactional执行事务了 -
@ComponentScan: 扫描被@Component注解的 bean,注解默认会扫描该类所在的包下所有的类包括了:
@MapperScan、@Mapper、@Repository都可以不用写,因为在application.yml中配置了mapper的接口路径 -
@Configuration: 允许在 Spring 上下文中注册额外的 bean 或导入其他配置类
注册Bean、装配Bean
-
注册
Bean两种方式:@Component:修饰类;里面的每个@Bean每次调用都是新实例
@Configuration:修饰类是特殊的@Component;里面的每个@Bean都是单例模式
@Bean:修饰被@Component、@Configuration标注的类中的成员方法
三层架构的类的注释(默认单例模式):@Controller(表现层)、@Service(业务层)、@Repository(持久层)@RestController相当于@Controller+@ResponseBodySpring
@Configuration和@Component区别)@Scope(···):
singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
prototype : 每次请求都会创建一个新的 bean 实例。
request : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。
session : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。@Profile(···): 指定环境变量下注册Bean@Mapper:Mybatis的注解,向Spring容器中注册Bean;等价于在启动类上扫描文件路径@MapperScan; 配置文件注意:需要把写
Mapper层的XML文件路径写在配置文件中application.yml中mybatis mapper-locations、配置Entity类路径mybatis typeAliasesPackage 持久层注册装配过程:
Spring会根据配置文件中的mybatis mapper-locations扫描所有的Mapper层的XML并根据在Mapper层的XML中使用namespace的全限定包名找到对应的DAO接口,并实现该DAO接口里面的每个成员方法生成一个新的DAO类Bean;且这个新的DAO类Bean的类型为DAO接口名,命名为首字母小写的DAO接口名;最后把这个新的DAO类Bean注册到Spring容器中;当Service层通过@Resource即可找到那个新的DAO类Bean并注入进来,至此整个持久层就串起来了。 扫描接口路径:
每个DAO接口类上都加上@Mapper<====等价于====>在启动类或自定义Mybatis配置类上使用@MapperScan。二者选一个即可、也可以都不加;因为只要Spring容器扫描XML文件,XML文件又能通过namespace找到DAO层接口。 配置
每个DAO类的成员方法实现类XML路径:在配置文件中application.yml中mybatis mapper-locations 配置
XML文件中简写返回类型的包路径:在配置文件中application.yml中mybatis typeAliasesPackage;推荐使用全限定名不要用alias -
装配
Bean: ——- 按名字装配性能最优
源自spring库:@Autowired默认按类型装配、@Autowired+@Qualifier(···)按名字装配;
源自java标准:@Resource(name="···")默认按名字装配、@Resource(type="···")注意:通常注解式装配
Bean直接是注入到成员变量中,相当于setter注入。
Spring boot将含有多个构造器的类注入到bean容器,并实现区分对同一个类不同bean名称的 bean的区分的四种方法
Spring Boot注解装配只能使用无参构造器,如果需要注入有参构造器的Bean则可以通过new getApplicationContext().getBean(clazz)(··参数··)
请求相关
- 请求方法注解:
@GetMapping(···)、@PostMapping(···)、@PutMapping(···)、@DeleteMapping(···)、@PatchMapping(···);
@RequestMapping(value="···",method=RequestMethod.POST)
2. 请求参数传值注解:
@PathVariable、@RequestParam、@RequestBody(替换@ModelAttribute)
请求参数校验
读取配置文件
@EnableConfigurationProperties
@PropertySource: 指定使用的配置文件
@ConfigurationProperties: @ConfigurationProperties(prefix = "···")
全局异常处理
@ControllerAdvice
@RestControllerAdvice(定义全局处理异常类): 相当于 @ControllerAdvice + @ResponseBody
@ExceptionHandler(写你想要拦截的异常类型)
解释: 被 @RestControllerAdvice 注解的类会自动注入到 控制器 的 请求方法注解(@RequestMapping)中
事务处理
ServiceImpl的方法中使用: @Transactional(rollbackFor = Exception.class)
json相关注解
其他Spring相关注解
-
@EnableXXX:
配合@Configuration使用,包括@EnableAsync,@EnableScheduling,@EnableTransactionManagement,@EnableAspectJAutoProxy,@EnableWebMvc。
通常Spring boot不需要配置,框架已经配置好了 -
@Lazy:
spring启动时不先实例化bean,等到使用时才开始实例化
Lombok库的注解
疑问
@Bean用于第三方组件的注册
Spring MVC相关
Spring的生命周期
实例化Bean启动时 BeanPostProcess
- Spring对Bean进行实例化(相当于程序中的new Xx())
- Spring将值和Bean的引用注入进Bean对应的属性中
- 如果Bean实现了BeanNameAware接口,Spring将Bean的ID传递给setBeanName()方法(实现BeanNameAware清主要是为了通过Bean的引用来获得Bean的ID,一般业务中是很少有用到Bean的ID的)
- 如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanDactory(BeanFactory bf)方法并把BeanFactory容器实例作为参数传入。(实现BeanFactoryAware 主要目的是为了获取Spring容器,如Bean通过Spring容器发布事件等)
- 如果Bean实现了ApplicationContextAwaer接口,Spring容器将调用setApplicationContext(ApplicationContext ctx)方法,把y应用上下文作为参数传入.(作用与BeanFactory类似都是为了获取Spring容器,不同的是Spring容器在调用setApplicationContext方法时会把它自己作为setApplicationContext 的参数传入,而Spring容器在调用setBeanDactory前需要程序员自己指定(注入)setBeanDactory里的参数BeanFactory )
- 如果Bean实现了BeanPostProcess接口,Spring将调用它们的postProcessBeforeInitialization(预初始化)方法(作用是在Bean实例创建成功后对进行增强处理,如对Bean进行修改,增加某个功能)
- 如果Bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet方法,作用与在配置文件中对Bean使用init-method声明初始化的作用一样,都是在Bean的全部属性设置成功后执行的初始化方法。
- 如果Bean实现了BeanPostProcess接口,Spring将调用它们的postProcessAfterInitialization(后初始化)方法(作用与6的一样,只不过6是在Bean初始化前执行的,而这个是在Bean初始化后执行的,时机不同 )
- 经过以上的工作后,Bean将一直驻留在应用上下文中给应用使用,直到应用上下文被销毁10.如果Bean实现了DispostbleBean接口,Spring将调用它的destory方法,作用与在配置文件中对Bean使用destory-method属性的作用一样,都是在Bean实例销毁前执行的方法。
监听器
- 实现
javax.servlet.ServletRequestListener,javax.servlet.http.HttpSessionListener, javax.servlet.ServletContextListener等等接口 - 主要用来监听对象的创建与销毁的发生, 比如 session 的创建销毁, request 的创建销毁, ServletContext 创建销毁
@Slf4j
@Component
@Conditional(JeecgCloudCondition.class)
public class SystemInitListener implements ApplicationListener<ApplicationReadyEvent>, Ordered {
@Autowired
private ISysGatewayRouteService sysGatewayRouteService;
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
log.info(" 服务已启动,初始化路由配置 ###################");
if (applicationReadyEvent.getApplicationContext().getDisplayName().indexOf("AnnotationConfigServletWebServerApplicationContext") > -1) {
sysGatewayRouteService.addRoute2Redis(CacheConstant.GATEWAY_ROUTES);
}
}
@Override
public int getOrder() {
return 1;
}
}
复制代码
Spring监听器—ApplicationListener与主动触发监听器
过滤器Filter
基于回调实现、属于web层,依赖于Servlet
适用于: 静态资源请求
// 首先 不需要任何@EnableXXX,只需要框架里有Servlet即可
// 第一步:自定义过滤器 ··· implements Filter
//重写方法 init、doFilter、destroy
//第二步:注入过滤器到spring容器中的2种方式
//1. 在自定义过滤器上直接使用注解
@Order
@WebFilter // 功能类似于FilterRegistrationBean注册过滤器
@WebInitParam
//2. 在注册了的Bean中代码形式注入过滤器
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean registFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean(); //属于Servlet中的一个方法,用于注册过滤器
registration.setFilter(new CostTimeFilter());
registration.addUrlPatterns("/*");
registration.setName("CostTimeFilter");
registration.setOrder(1);
return registration;
}
}
复制代码
拦截器
基于反射和AOP思想,拦截控制器,依赖于Spring框架
适用于: 统一权限控制、动态请求
// 首先开启 @EnableWebMvc,Spring Boot默认已经开启
// 第一步:自定义拦截器 ··· extends HandlerInterceptor/HandlerInterceptorAdapter
// 重写方法 preHandle、postHandle、afterCompletion
// 第二步:注入拦截器 ··· implements WebMvcConfigurer
复制代码
Aspet—AOP
拦截Service
实际开发中,AOP常和事务结合
AOP的实现原理—-本质是反射
服务器定位模式(Service Locator) < == == > 委托模式(delegate)< == == > 反射、动态代理 < == ==> 类的方法不是由自己的实例调用,而是委托给用户自主调用
Spring默认使用cglib库的反射实现,没有用jdk自带的反射
控制器 servlet、controller
解析器 ··· implements HandlerMethodArgumentResolver
方法参数解析器:适用于使用注解使控制器方法参数的运行时修改
视图解析器(ViewResolver)
语言解析器
// 首先开启 @EnableWebMvc,Spring Boot默认已经开启
// 第一步:自定义解析器 ··· implements HandlerMethodArgumentResolver/··· extends AbstractNamedValueMethodArgumentResolver
// 重写方法 createNamedValueInfo、resolveName、supportsParameter、handleMissingValue
// 第二步:注入解析器 ··· implements WebMvcConfigurer
复制代码
spring发起一个请求的过程
容器启动、销毁等事件的监听器(ApplicationListener或自定义事件监听) ->
前端控制器(DispatcherServlet) -> 请求到处理器映射(HandlerMapping) -> 过滤器(Filter) -> Servlet容器(Tomcat) -> 拦截器(Interceptor) -> 解析器(Resolver) -> AOP -> 控制器(Controller) -> 验证器(Validator) -> 命令对象(Command 请求参数绑定到的对象就叫命令对象)-> 表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象;就是需要返回给前端的值)
Spring过滤器与拦截器-代码实现
过滤器、拦截器区别
拦截器、过滤器区别—知乎
spring生命周期
Spring架构
spring boot常用组件
监控模块
Spring Boot Actuator 与 Micrometer
Spring MVC
模型(Model)中注入数据
请求参数校验
使用方式
- 在controller中的参数中使用
@Validated - 在
entity文件中使用@valid注解标注 以校验 集合中的元素 和 自定义数据类型 - 自定义校验器,统一错误信息返回格式
Spring中的零散知识点
路径匹配
**: 表示任意多级目录
*: 表示任意名称的目录
classpath*:与classpath::打包速度前者慢些
classpath*:org/jeecg/modules/**/xml/*Mapper.xml: 此种方式能匹配到与输出目录classes同级的jar包内部的文件
classpath*:/mapper/**/*.xml:输出目录中的静态资源
Spring中的Bean默认是单例模式,为什么可以并发请求
单例模式的成员变量必须保证线程安全,如用ThreadLocal,单例的方法及其局部变量每次调用都会创建在自己的方法栈上下文中,因此可以保证并发而互不影响。
所以Spring中的所有注册的类的成员变量有两种情况:
- 成员变量是使用
@Autowired等注解,且这个成员变量的类定义中成员方法也满足条件1、条件2 - 成员变量是其他普通类型,如
int、List、Set、Map等,则必须手动保证线程安全ThreadLocal,
spring boot web层基于servlet,servlet的每个request是一个线程;而且数据库连接也要保证线程隔离,因为临时表、绑定变量等都只在当前会话有效,且不同会话互相隔离,才有意义;当有要求单次请求中需要多次操作数据库,必须把多次操作封装在一个事务中。
在同一个方法中,Mybatis多次请求数据库,是否要创建多个SqlSession会话? – 简书 (jianshu.com)
spring中的mybatis的sqlSession是如何做到线程隔离的? – 等你归去来 – 博客园 (cnblogs.com)






















![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)