对于spring的一个理解 分为IOC和AOP IOC解决的是对象的管理和对象的依赖问题 本身是自己手动new对象,现在把对象交给IOC容器管理 IOC容器可以理解为一个对象工厂,我们都把该对象交给工厂,工厂管理这些对象的创建以及依赖关系,我们需要对象的时候再去取就好了 IOC是控制反转,把自己主动创建对象的过程变成一个比较被动的过程,把自己的事去交给别人管理,是一种思想和设计模式。 依赖注入是控制反转的实现的一种方式,对象无需自行创建管理他的依赖关系,依赖关系将被自动注入到他们所需要的对象当中去。 AOP:解决的是非业务代码的抽取问题 底层是动态代理,在Spring内实现依赖的是BeanPostProcessor 我们在方法上注入些重复性的非业务代码的时候可以用AOP。所谓面向切面编程就是在方法前后增加非业务代码。 比如日志操作啊等 动态代理一个是JDK的proxy还有一个是cgLib jdk的proxy可以生成语言接口,就是语言实现相同的接口这么一个类,如果原来的类没有实现的话,他就不太适合 如果是CGLib的话他会使用一种字节码的编译器ASM的一个编译器,可以去生成目标类的一个子类,去实现类的一个代理的功能 性能上CGLib在创建对象的过程中可能会慢一些,但是在运行的时候效率可能会更高一些。 什么是动态代理 动态代理是代理模式的一种,代理是设计模式之一 代理模型有静态代理和动态代理,静态代理需要直接去写代理类实现对应的接口是比较麻烦的 java动态代理有JDK动态代理和CGLib代理 JDK动态代理重要的是使用反射机制而CGlIB用的是ASM框架,修改字节码生成子类来处理 举例子mybatis不用写实现类只写接口就可以执行sql还有aop用的都是动态代理 ioc是如何创建对象的/项目如何把对象交给IOC管理 spring IoC容器,负责创建Bean,并通过容器将功能类Bean注入到用户需要的Bean中,spring提供了四种方式,spring提供使用xml、注解、java配置、groovy配置实现Bean的创建和注入 我们一般使用注释或者xml比较多,少部分用javaConfig 日常写代码一般用注释来定义各种对象,责任链这种一般配置在xml,注释解决不了的用javaConfig 如何去创建 首先定义一个数据实体类然后里面写上get,set方法定义了一个实体后,定义一个service封装了一个相关业务操作,其他的类,至于要注入这个service,就可以使用了然后通过注解的方式,把对象加入ioc容器,创建对象以及处理对象依赖关系,在controller中接受用户的请求后,可以编写接口,将需要的@service注入,并完成相关的业务逻辑 响应的注解 @Component 指定把一个对象加入IOC容器 @Repository 作用同@Component; 在持久层使用 @Service 作用同@Component; 在业务逻辑层使用 @Controller 作用同@Component; 在控制层使用 @Resource 属性注入 @Autowired 自动装配 正常new创建对象的生命周期
分为三个阶段
加载:将jvm字节码加载到内存中去,jvm使用双亲委派机制保护jvm内部安全,以防止类的重复加载
连接分为三个阶段
1.验证:主要验证加载文件是否符合jvm规范
2.准备:为静态变量赋予零值,类变量如果被final修饰则直接赋予定义的值,类变量如果被final修饰则直接赋予定义的值
3.解析:将符号引用转化为直接引用
初始化:为静态变量赋值,成员变量赋零值,执行静态代码块。
springBean生命周期
SpringBean的生命周期分为五个阶段,分别是创建前准备,创建实例化,依赖注入,容器缓存,和销毁实例这几个阶段。
创建前准备:这个阶段的主要作用是,Bean在开始加载前,要从上下文和一些配置中,去解析并且查找Bean有关的扩展实现,比如说像init-method,容器在初始化时候会调用的一些方法destroy method容器在销毁Bean的时候会调用的喜喜呃方法,以及BeanfactoryPostProcessor这一系列的Bean加载过程中的一些,前置和后置的一些处理扩展的实现,这些类或者配置其实是Spring提供给开发者来去实现Bean加载中的一些扩展,在很多和Spring集成的中间件也比较常见
创建是创建实例化阶段:主要作用是通过反射,去创建Bean的实例对象,并且会扫描和解析Bean的一些属性
依赖注入阶段:如果被实例化的Bean存在依赖其他Bean对象的一些情况,则需要对这些依赖的Bean进行对象注入比如@Autowired以及setter注入,这些配置形势,同时在这个阶段,会触发一些扩展的调用,比如常见的扩展类BeanPostProcessors用来实现Bean初始化前后的扩展回调以及像BeanFactoryAware等等
容器缓存:主要是把Bean保存到容器以及Spring的缓存中这个阶段Bean就可以被开发者去使用了,常见的操作像init-method这个属性配置一些方法,会在这个阶段进行调用以及像BeanPostProcessors的后置处理器方法,也会在这个阶段被处罚
销毁实例:当spring的应用上下文被关的时候,这个上下文所有的Bean会被关闭的时候,上下文中所有的Bean会被销毁,如果存在Bean实现了DisposableBean接口或者配置了destroy method的一些属性的一些方法,会在这个阶段被调用。
BeanDefinition关于Bean的描述
# SpringBoot自动装配原理
就是会有一个# @SpringBootApplication注解是一个组合注解然后他的源码里面主要有三个注解
1.@ComponentScan,是一个扫描包,找到那些包符合要求到我们的容器中
2.@EnableAutoConfiguration,里面也有一些组合注解@Import(EnableAutoConfigurationImportSelector.class),其中有一个非常重要的方法importselect(选取一些类,注入到我们的ioc容器中)
3.@SpringBootConfiguration,代表了一个配置类,相当于一个beans.xml文件,是SpringBoot的配置
mybatis里面的执行器
Executor执行器
里面功能做一下总结
基本功能:改、查,没有增删的原因是所有的增删操作都可以归结到改。
缓存维护:这里的缓存主要是为一级缓存服务,功能包括创建缓存Key、清理缓存、判断缓存是否存在。
事务管理:提交、回滚、关闭、批处理刷新。(一般我们都交由spring管理,不会使用mybatis的)
Executor有主要的三个实现子类。分别是:SimpleExecutor(简单执行器)、ReuseExecutor(重用执行器)、BatchExecutor(批处理执行器)。
简单执行器 SimpleExecutor是默认执行器,它的行为是每处理一次会话当中的SQl请求都会通过对应的StatementHandler 构建一个新个Statement,这就会导致即使是相同SQL语句也无法重用Statement,所以就有了(ReuseExecutor)可重用执行器
可重用执行器 ReuseExecutor 区别在于他会将在会话期间内的Statement进行缓存,并使用SQL语句作为Key。所以当执行下一请求的时候,不在重复构建Statement,而是从缓存中取出并设置参数,然后执行。阅读源码可以知道其实里面就包含一个statementMap,执行的时候看一下是否存在,如果有了就不需要新构建statement了
这也说明为什么执行器不能跨线程调用,这会导致两个线程给同一个Statement 设置不同场景参数。
批处理执行器 BatchExecutor 顾名思议,它就是用来作批处理的。但会将所有SQL请求集中起来,最后调用Executor.flushStatements() 方法时一次性将所有请求发送至数据库。