spring

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

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,大大简化配置流程。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值