spring总结
简单介绍一下spring?
spring是一个轻量级的开源框架,它的主要核心是IOC(控制反转);DI(依赖注入);和AOP (面向切面编程)
IOC :将对象的创建权反转给spring,作用是实现了程序的解耦。
**DI :依赖注入,在spring创建Bean时,动态的将依赖对象注入到Bean对象中去,依赖注入最大的好处就是解耦合。
springIOC容器:,对于 Spring 框架来说,接口ApplicationContext代表高级的 IoC 容器;BeanFactory是基础版低级的IOC容器。Spring IoC 容器负责创建 Bean(对象),通过容器将功能类 Bean 注入到你需要的 Bean 中。Spring 框架提供了多个接口ApplicationContext的实现,包括ClassPathXmlApplicationContext,FileSystemXmlApplicationContext,以及WebApplicationContext。Spring IoC 容器使用 xml 配置,或者注解配置来实现 Bean 的创建与注入。
BeanFactory和ApplicationContext的区别?
1.BeanFactory是spring最顶层的接口,包含各种Bean的定义,读取Bean的配置文档,管理Bean的加载,实例化,控制Bean的生命周期,维护Bean之间的依赖关系;ApplicationContext是BeanFactory的子接口,除了BeanFactory所具有的功能外,还具有更完整的框架功能;如:
- 继承MessageSource,支持国际化
- 统一资源文件访问等
2.BeanFactory采用延迟加载,第一次调用getBean时才会初始化Bean;ApplicationContext是会在加载配置文件时初始化Bean。
spring依赖注入的几种方式?
- 构造方法注入
使用方式:
第一,在类中,不用为属性设置setter方法(但是可以有),但是需要生成该类带参的构造方法。
第二,在配置文件中配置该类的bean,并配置构造器,在配置构造器中用到了节点,该节点有四个属性:
- index是索引,指定注入的属性位置,从0开始;
- type是指该属性所对应的类型;
- ref 是指引用的依赖对象;
- value 当注入的不是依赖对象,而是基本数据类型时,就用value;
<!-- 构造函数注入(按类型匹配) -->
<bean id="car1" class="com.spring.model.Car">
<constructor-arg type="int" value="300"></constructor-arg>
<constructor-arg type="java.lang.String" value="宝马"></constructor-arg>
<constructor-arg type="double" value="300000.00"></constructor-arg>
</bean>
- set方法注入
属性注入要求Bean提供一个默认的无参构造函数,并为需要注入的属性提供对应的Set/get方法。Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值。
<bean id=”……” class=”……”>
<property name=”属性1” value=”……”/>
<property name=”属性2” ref=”……”/>
……
</bean>
- 注解注入
通过在 xml 中导入 p 名称空间,使用 p:属性名来注入数据,它的本质仍然是调用类中的set 方法实现注入功能
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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="accountService"
class="com.yooyo.service.impl.AccountServiceImpl4"
p:name="test" p:age="21" p:birthday-ref="now"/>
</beans>
spring ioc的初始化流程
resource定位 即寻找用户定义的Bean资源,由ResourceLoader通过统一的接口Resource接口来完成beanDefinition载入BeanDefinitionReader读取,解析resource定位的资源,完成BeanDefinition载入到ioc中(通过hashMap维护DB)
第一个过程是Resource资源定位。这个Resouce指的是BeanDefinition的资源定位。这个过程就是容器找数据的过程,就像水桶装水需要先找到水一样。
第二个过程是BeanDefinition的载入过程。这个载入过程是把用户定义好的Bean表示成Ioc容器内部的数据结构,而这个容器内部的数据结构就是BeanDefition。
第三个过程是向IOC容器注册这些BeanDefinition的过程,这个过程就是将前面的BeanDefition保存到HashMap中的过程
spring容器中Bean的作用域
-
singleton:单例;容器默认为单例的,即不管有多少个请求,每个容器中只有一个Bean实例
-
prototype:原型;与单例相反,为每一个Bean请求提供一个实例
-
request:每次httpt请求都会创建一个Bean实例,请求完成后Bean会失效并被垃圾回收。
-
session,为每一个session都提供一个Bean,在session过期后bean会随之失效
-
global-session:在一个全局的HTTP Session中,y一个Bean的定义对应一个实例
request session global-session 这三种作用域都是基于web 的spring ApplicationContext情形下有效
spring Bean的生命周期
(1)实例化一个Bean--也就是我们常说的new;
(2)按照Spring上下文对实例化的Bean进行配置--也就是IOC注入;
(3)如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id值;
(4)如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(setBeanFactory(BeanFactory)传递的是Spring工厂自身(可以用这个方式来获取其它Bean,只需在Spring配置文件中配置一个普通的Bean就可以);
(5)如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文(同样这个方式也可以实现步骤4的内容,但比4更好,因为ApplicationContext是BeanFactory的子接口,有更多的实现方法);
(6)如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化结束时调用那个的方法,也可以被应用于内存或缓存技术;
(7)如果Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法。
(8)如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法、;
注:以上工作完成以后就可以应用这个Bean了,那这个Bean是一个Singleton的,所以一般情况下我们调用同一个id的Bean会是在内容地址相同的实例,当然在Spring配置文件中也可以配置非Singleton。
(9)当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法
(10)最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
另外我们这里描述的是应用Spring上下文Bean的生命周期,如果应用Spring的工厂也就是BeanFactory的话去掉第5步就Ok了
Spring AOP
1.什么是AOP?
AOP是不同于OOP编程思想,OOP(面向对象编程)是一种至上而下的编程方式,而AOP是横切性的编程思想;
2.AOP的实现方式?
AOP实现的关键在于 代理模式,AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ;动态代理则以Spring AOP为代表。
(1)AspectJ是静态代理,也称为编译时增强,AOP框架会在编译阶段生成AOP代理类,并将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象。
(2)Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。
AspectJ注解关键字
- 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务无关的,但需要我们关注的部分,就是横切关注点,如:日志,安全,缓存,事务d等等
- 切面(Aspect):横切关注点,被模块化的特殊对象。即,它是一个类。
- 通知(Advice):切面必须完成的工作。即,他是类中的一个方法。
- 目标(Target):被通知对象。
- 代理(Proxy):向目标对象应用通知之后创建的对象。
- 切入点(PointCut):切面通知执行的“地点”的定义(表达式)。
- 连接点(JiontPoint):与切入点匹配的执行点。
一.基于注解(AspectJ方式)
package com.spring.aop;
@Aspect //标注这个类是一个切面
public class AopAspectJ {
/**
* 必须为final String类型的,注解里要使用的变量只能是静态常量类型的
*/
public static final String EDP="execution(* com.spring.service.impl.UserManagerServiceImpl..*(..))";
/**
* 切面的前置方法 即方法执行前拦截到的方法
* 在目标方法执行之前的通知
* @param jp
*/
@Before(EDP)
public void doBefore(JoinPoint jp){
System.out.println("=========执行前置通知==========");
}
/**
* 在方法正常执行通过之后执行的通知叫做返回通知
* 可以返回到方法的返回值 在注解后加入returning
* @param jp
* @param result
*/
@AfterReturning(value=EDP,returning="result")
public void doAfterReturning(JoinPoint jp,String result){
System.out.println("===========执行后置通知============");
}
/**
* 最终通知:目标方法调用之后执行的通知(无论目标方法是否出现异常均执行)
* @param jp
*/
@After(value=EDP)
public void doAfter(JoinPoint jp){
System.out.println("===========执行最终通知============");
}
/**
* 环绕通知:目标方法调用前后执行的通知,可以在方法调用前后完成自定义的行为。
* @param pjp
* @return
* @throws Throwable
*/
@Around(EDP)
public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("======执行环绕通知开始=========");
// 调用方法的参数
Object[] args = pjp.getArgs();
// 调用的方法名
String method = pjp.getSignature().getName();
// 获取目标对象
Object target = pjp.getTarget();
// 执行完方法的返回值
// 调用proceed()方法,就会触发切入点方法执行
Object result=pjp.proceed();
System.out.println("输出,方法名:" + method + ";目标对象:" + target + ";返回值:" + result);
System.out.println("======执行环绕通知结束=========");
return result;
}
/**
* 在目标方法非正常执行完成, 抛出异常的时候会走此方法
* @param jp
* @param ex
*/
@AfterThrowing(value=EDP,throwing="ex")
public void doAfterThrowing(JoinPoint jp,Exception ex) {
System.out.println("===========执行异常通知============");
}
}
需要配置里面开启注解支持
//proxy-target-class='flase'是默认的为Jdk动态代理 ;
//proxy-target-class='true' 即使用cglib动态代理 ;
<aop:aspectj-autoproxy proxy-target-class='flase'>
二:基于XML配置的Spring AOP
定义切面类:
package com.spring.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class AopAspect {
/**
* 前置通知:目标方法调用之前执行的代码
* @param jp
*/
public void doBefore(JoinPoint jp){
System.out.println("===========执行前置通知============");
}
/**
* 后置返回通知:目标方法正常结束后执行的代码
* 返回通知是可以访问到目标方法的返回值的
* @param jp
* @param result
*/
public void doAfterReturning(JoinPoint jp,String result){
System.out.println("===========执行后置通知============");
System.out.println("返回值result==================="+result);
}
/**
* 最终通知:目标方法调用之后执行的代码(无论目标方法是否出现异常均执行)
* 因为方法可能会出现异常,所以不能返回方法的返回值
* @param jp
*/
public void doAfter(JoinPoint jp){
System.out.println("===========执行最终通知============");
}
/**
*
* 异常通知:目标方法抛出异常时执行的代码
* 可以访问到异常对象
* @param jp
* @param ex
*/
public void doAfterThrowing(JoinPoint jp,Exception ex){
System.out.println("===========执行异常通知============");
}
/**
* 环绕通知:目标方法调用前后执行的代码,可以在方法调用前后完成自定义的行为。
* 包围一个连接点(join point)的通知。它会在切入点方法执行前执行同时方法结束也会执行对应的部分。
* 主要是调用proceed()方法来执行切入点方法,来作为环绕通知前后方法的分水岭。
*
* 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法。
* 而且环绕通知必须有返回值,返回值即为目标方法的返回值
* @param pjp
* @return
* @throws Throwable
*/
public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("======执行环绕通知开始=========");
// 调用方法的参数
Object[] args = pjp.getArgs();
// 调用的方法名
String method = pjp.getSignature().getName();
// 获取目标对象
Object target = pjp.getTarget();
// 执行完方法的返回值
// 调用proceed()方法,就会触发切入点方法执行
Object result=pjp.proceed();
System.out.println("输出,方法名:" + method + ";目标对象:" + target + ";返回值:" + result);
System.out.println("======执行环绕通知结束=========");
return result;
}
}
xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- 声明一个业务类 -->
<bean id="userManager" class="com.spring.service.impl.UserManagerServiceImpl">
<property name="name" value="lixiaoxi"></property>
</bean>
<!-- 声明通知类 -->
<bean id="aspectBean" class="com.spring.aop.AopAspect" />
<aop:config>
<aop:aspect ref="aspectBean">
<aop:pointcut id="pointcut" expression="execution(* com.spring.service.impl.UserManagerServiceImpl..*(..))"/>
<aop:before method="doBefore" pointcut-ref="pointcut"/>
<aop:after-returning method="doAfterReturning" pointcut-ref="pointcut" returning="result"/>
<aop:after method="doAfter" pointcut-ref="pointcut" />
<aop:around method="doAround" pointcut-ref="pointcut"/>
<aop:after-throwing method="doAfterThrowing" pointcut-ref="pointcut" throwing="ex"/>
</aop:aspect>
</aop:config>
</beans>
spring aop的应用场景
1.权限(Authentication)
2.缓存(Caching)
3.错误处理
4.记录日志(loging)
5.事务(transaction)
spring三级缓存
1.singletonObjects:第一级,单例缓存池。用于完全初始化好的Bean,从该缓存中取出的Bean可以直接使用。
2.earlySingletonObjects:第二级缓存。提前曝光的单例对象的cache,存放原始的Bean对象(尚未填充属性的Bean)
3.singletonFactories:第三级,单例对象工厂缓存。单例对象工厂的cache,存放bean工厂对象。
spring如何处理线程并发问题
spring使用ThreadLocal解决线程安全问题。
当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
在一般境况下,只有无状态的Bean才可以在多线程环境下共享,在spring中,绝大多数Bean都可以声明为singleton的作用域。就是因为spring对一些Bean中非线程安全状态采用ThreadLocal进行处理,让他们成为线程安全状态,因此有状态的Bean就可以在线程中共享了
springMVC总结
springMVC工作原理
springMVC框架式围绕一个DispatcherServlet来设计的,这个servlet会把请求分发给各个处理器,并支持可配置的处理器映射,视图渲染,本地化,时区主题渲染等,甚至还支持文件上传。
springMVC执行流程:
1.HTTP请求到DispatcherServlet (客户端请求提交到DispatcherServlet.)
2.HandlerMapping寻找处理器 (由DispatcherServlet查询一个或多个HandlerMapper,找到处理请求的controller)
3.调用处理器controller (DispatcherServlet将请求提交到Controller)
4.Controller调用业务逻辑处理后,返回ModelAndView
5.DispatcherServlet查询ModelAndView (Dispatcher查询一个或多个ViewResoler视图解析器,找到ModelAndView指定视图)
6.ModelAndView反馈浏览器HTTP (试图负责将结果显示到客户端)
springMVC拦截器
1.定义一个interceptor类要实现spring的HandlerIntercepter接口
2.继承实现了HandlerInterceptor接口的类,比如spring已经提供的HandlerInterceptorAdapter
hanlerInterceptor接口定义了三个方法,我们通常就是通过这三个方法对请求进行拦截处理
- prehandle() ;这个方法在业务处理器处理之前没调用
- posthandle();这个方法在请求处理之后被调用
- afterCompletion();这个需要当前对应的interceptor的preHandle方法返回true时才会执行。
拦截器与过滤器区别
过滤器filter ;拦截器intercepter
过滤器是在java web中将你传入的request,response提前过滤掉一些信息,或者提前设置一些参数。然后再servlet进行业务逻辑处理(比如过滤掉非法url)
拦截器也是面向切面编程(aop)的一种思想,就是在一个方法调用前,或在方法调用后,比如动态代理就是拦截器的简单实现
SpringBoot总结
什么是SpringBoot
SpringBoot是Spring开源组织下的子项目,主要是简化使用Spring的难度,省略繁重的配置,提供各种启动器,开发者能快速上手。
SpringBoot有哪些优点
1.容易上手,提高开发效率。
2.开箱即用,简化Maven配置,远离繁琐配置。
3.没有代码生成,不需要繁琐的XML配置。
Spring Boot的核心注解有哪些
启动类上面的注解是 @SpringBootApplication ;他主要包含一下三个注解:
- @SpringBootConfiguration:组合了@Configuration注解,实现配置文件的功能
- @EnableAutoConfiguration:打开自动配置功能,也可以关闭某个自动配置选项,如关闭数据源自动配置功能:@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})。
- @ComponentScan:spring组件扫描
- @component注解在类上,表示一个通用bean,value默认就是类名的首字母小写
- @Autowired按类型注入(默认属性为required=true,当不确定容器中是否有某个ben时,可将required=flase)@Autowired是spring的注解
- @Resource:按名称匹配 @resource是j2ee的注解
- @bean,注解在方法上,表示返回一个bean
- configuration:注解在类上,表示这是一个ioc容器,一般和@bean注解配合使用。
Spring Boot自动配置原理是什么
@EnableAutoConfiguration就是位springBoot实现自动配置的核心注解。它的意思就是开启自动配置功能。
@EnableAutoConfiguration内部有两个非常重要的注解,分别是@AutoConfigrationPackage和@Import(AutoConfigurationImportSelector.class)
@AutoConfigurationPackag注解的作用就是将springBoot主配置类所在的包及其所有子包里面的所有组件扫面到spring容器中。
@Import(AutoConfogurationSelector.class)注解的作用时导入AutoConfigurationImoprtSelector组件,也就是自动配置导入选择器,它可以选择需要的组件进行导入。
总结:SpringBoot在启动的时候就从类路径的MATE-INF/spring.factories中获取EnableAutoConfiguration的指定值,并将这些值加载到自动配置类导入到容器中,自动配置类就生效了,帮助我们进行自动配置。
Spring Boot的核心配置文件是什么
Spring Boot的核心配置文件有两个:bootstarp.properties(或者.yml):
- bootstarp由由父ApplicationContext加载的;比application优先加载,配置在应用程序上下文的引导阶段生效。一般来说在spring cloud fonfig或者nacos中会使用到它,特别是需要加载一些远程配置文件的时候。且bootstarp里面的属性不能被覆盖。
- application.properties(或者.yml):由ApplicationContext加载,用于SpringBoot项目的自动化配置。
spring,springMVC,springBoot关系与区别
1.spring是一个一站式的轻量级的java开发框架,核心是ioc和面向切面编程。
2.springMVC是基础上的一个mvc框架,主要处理web开发的路径映射和视图渲染,属于spring框架中web层开发的一部分。
3.springBoot框架相对于mvc框架来说它遵循默认优于配置,简化插件配置流程,不需要配置xml,大大简化配置流程。