一、Spring IOC
IOC控制反转,是一种思想,意味着将你设计好的对象交给容器控制而非自己直接控制,使用时由容器创建及注入依赖对象。
DI依赖注入,组件间的依赖关系由容器在运行时决定;依赖注入的目的并非为软件系统带来更多功能,而是提升组件重用的频率。
https://www.cnblogs.com/xdp-gacl/p/4249939.html
二、Spring Bean加载流程
Spring Bean初始化过程:首先读取XML中的bean(id、class、scope、depends on、lazyInit、init-method、destroy-method)初始化为BeanDefinition;通过BeanDefinition将bean注册至DefaultListableBeanFactory保存在一个ConcurrentHashMap;将bean注册后Spring提供扩展的切口允许通过实现BeanFactoryPostProcessor插入自定义代码(例如PropertyPlaceholderConfigurer处理配置中${}占位符为实际值);
Bean的实例化阶段通过反射或者Cglib对Bean进行实例化,暴露很多扩展点;实现BeanFactoryAware、MessageSourceAware、ApplicationContextAware等Aware接口,实例化bean时Spring会注入对应的BeanFactory、MessageSource、ApplicationContext实例;实现BeanFactoryProcessor接口的bean,实例化bean时Spring调用接口的方法,postProcessBeforeInitialization方法在InitializingBean接口的 afterPropertiesSet方法之前执行,而postProcessAfterInitialization方法在 InitializingBean接口的afterPropertiesSet方法之后执行;InitializingBean接口和 DisposableBean接口对应于<bean/>的init-method和destory-method属性;
实现FactoryBean接口的bean其特点是spring使用getBean()获取bean时会自动调用该Bean的getObject()方法,返回不是factory这个bean而是bean.getObject()方法的返回值,如spring集成mybatis时返回SqlSessionFactory而不是org.mybatis.spring.SqlSessionFactoryBean(SqlSessionFactoryBean是生产SqlSessionFactory的工厂,而SqlSessionFactory又是生产SqlSession的工厂)。
依赖注入的方式分为构造函数<constructor-arg>注入和setter方法<property>注入。
Spring Bean的生命周期
影响多个Bean的接口(实现接口的Bean会切入到多个Bean的生命周期):InstantiationAwareBeanPostProcessor(实例化阶段前后,postProcessBeforeInstantiation方法在自定义了TargetSource时替换代理类、postProcessAfterInstantiation方法在属性赋值方法内,但在真正执行赋值操作之前,返回值为boolean,false时可阻断属性赋值阶段,非自定义TargetSource时替换代理类,Spring AOP实现)BeanPostProcessor(初始化阶段前后,也是postProcessBeforeInstantiation、postProcessAfterInstantiation方法)、
影响单个Bean的接口(Aware类接口,如BeanNameAware、BeanClassLoaderAware、BeanFactoryAware(初始化阶段之前调用)、EnvironmentAware、EmbeddedValueResolverAware、ApplicationContextAware(postProcessBeforeInstantiation方法调用))
两个生命周期接口:InitializingBean(初始化阶段,除实现InitializingBean接口外还可通过注解或者xml配置的方式指定初始化方法)、DisposableBean(销毁阶段,以ConfigurableApplicationContext#close()方法作为入口,实现是通过循环取所有实现DisposableBean接口Bean然后调用destroy方法)
BeanPostProcessor也会注册为Bean,Spring首先调用registerBeanPostProcessors()进行BeanPostProcessors的注册,然后执行finishBeanFactoryInitialization初始化单例非懒加载的Bean。BeanPostProcessor可以存在多个,每个BeanPostProcessor均影响多个Bean,不同实例执行顺序通过继承排序接口PriorityOrdered、Ordered实现,实现PriorityOrdered接口首先被执行,同继承PriorityOrdered接口的实例之间通过接口返回值排序,而实现Ordered接口其次被执行,未实现接口最后执行
三、Spring AOP
Spring AOP面向切面编程,面向对象编程的补充(面向对象编程的关键单元是对象,面向切面编程的关键单元是切面),简而言之就是在方法执行前后添加一段代码。使用场景一般为:事务、权限、日志、安全等。
concern和cross-cutting concern:关注点即在应用模块中实现的行为;横切关注点即贯穿整个应用程序的关注点(日志、安全、数据转换);
AOP的实现:Aspect、Spring AOP(Aspect注解风格和Spring XML配置风格)、Jboss AOP
Spring通知类型:Before前置通知、After后置通知、AfterReturning正常返回通知、AfterThrowing抛出异常通知、Around环绕通知
Spring AOP代理:默认使用JDK动态代理(针对接口),针对非接口使用Cglibc代理。
引介(Introduction):可以让一个切面声明被通知的对象实现没有实现的额外接口(@DeclareParaents)
连接点Joint Point和切入点Point Cut:连接点是程序执行的一个点,代表一个方法执行。切入点是匹配连接点的一个断言或者表达式。
Weaving织入:Spring AOP仅支持Aspectj几个类型的切入点类型,允许将AOP运用到IOC的声明的Bean中。若想使用额外的切入点类型,则直接使用Aspectj框架使用它的织入特性。
Aspectj编译时织入:通过ajc特殊的Aspectj编译器完成,编译时将切面织入到java源码文件,输入织入的class文件。
Aspectj编译后织入:通过ajc特殊的Aspectj编译器可以将切面织入到编译后的class文件或jar中
Aspectj加载时织入(LTW):在目标类被类加载器加载至JVM时触发,被注入对象需要一个特殊的类加载器来增强目标类的字节码。
https://blog.csdn.net/dadiyang/article/details/82920139
四、Spring MVC流程
1、客户端(浏览器)发动请求,直接到DispatcherServlet
2、DispatcherServlet根据请求信息调用HandlerMapping,解析相应的Handler
3、解析到的Handler由HandlerAdapter处理,请求并处理业务逻辑
4、Handler处理后返回ModelAndView对象(Model表示数据对象,View表示逻辑View)
5:ViewResolver根据逻辑View解析实际View(JSP等)
6:DispatcherServlet将返回的Model传给View(视图渲染)
7:最后将View返回给请求者(浏览器)
Spring MVC创建拦截器:实现HandlerInterceptor/继承HandlerInterceptorAdapter
通过mvc xml配置、继承WebMvcConfigurerAdapter、WebMvcConfigurationSupport重写拦截器addInterceptors方法、反射方式获取bean处理interceptors属性字段。
五、Mybatis
Mybatis是一个半ORM(对象关系映射,但需手动编写SQL)框架,内部封装JDBC,加载驱动、创建连接、创建statement等繁杂的过程,开发者开发时只需关注如何编写SQL语句,即可严格控制sql执行性能,灵活度高。
Mapper接口的工作原理是JDK动态代理,Mybatis运行时使用JDK动态代理为Mapper接口生成代理对象proxy,代理对象会拦截接口方法,根据接口名称、方法名,唯一定位一个MapperStatement,之后调用执行器执行配置SQL,最后将SQL执行结果返回。
Mybatis集成Spring初始化时将包路径下的所有Mapper接口注册到Spring Bean中,并将beanClass设置为MapperFactoryBean。MapperFactoryBean实现FactoryBean接口。当通过 @Autowired 注入Dao接口的时候,返回对象即MapperFactoryBean的getObject()方法对象。该方法通过JDK动态代理,返回了一个Mapper接口的代理对象(代理对象处理器是MapperProxy对象),当调用接口的方法,则调用到MapperProxy对象的invoke()方法。
5.1 缓存机制
一级缓存: 基于PerpetualCache的HashMap本地缓存,存储作用域为Session,当Session flush或close后,该Session中所有Cache将清空,默认打开一级缓存。
二级缓存:默认采用 PerpetualCache的HashMap存储,存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认未打开,若需开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),配置标签 <cache/> ;
缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)进行了C/U/D 操作后,默认该作用域下所有 select 中缓存将被 clear 掉并重新更新,若开启了二级缓存,则只根据配置判断是否刷新。
Spring集成mybatis后原DefaultSqlSession被替换为SqlSessionFatory调用时每次获取新的SqlSession,由于一级缓存基于Session因此一般情况下一级缓存失效,而当使用事务使用ThreadLocal保证事务中获取到的SqlSession相同,一级缓存才生效
5.2 延迟加载
Mybatis仅支持association关联对象和collection关联集合对象的延迟加载(配置是否启用延迟加载:lazyLoadingEnabled=true|false)。
延迟加载的基本原理:使用cglib创建目标对象的代理对象,当get目标对象的某个属性时,拦截器invoke()方法发现该属性是NULL值,则调用关联对象或集合对象的SQL,查询结果后set属性值,接着get属性值时正常返回。
5.3 接口绑定
mybatis接口绑定2种实现方式:
1、基于XML配置
2、基于@Select、@Insert、@Update、@Delete注解配置