打开资料 https://github.com/brianway/springmvc-mybatis-learning SpringMVC 和 MyBatis 学习笔记,搭配示例,主要讲解一些基础的概念、用法和配置
[完整登录流程分析] 参考 https://www.cnblogs.com/haolnu/p/7294533.html
web.xml
<context-param>的作用: 2.紧接着,容器创建一个ServletContext(上下文),这个WEB项目所有部分都将共享这个上下文. 3.容器将<context-param></context-param>转化为键值对,并交给ServletContext. 4.容器创建<listener></listener>中的类实例,即创建监听. 5.在监听的类中会有一个contextInitialized(ServletContextEvent event)初始化方法,在这个方法中可以通过event.getServletContext().getInitParameter("contextConfigLocation") 来得到context-param 设定的值。在这个类中还必须有一个contextDestroyed(ServletContextEvent event) 销毁方法.用于关闭应用前释放资源,比如说数据库连接的关闭。 6.得到这个context-param的值之后,你就可以做一些操作了.注意,这个时候你的WEB项目还没有完全启动完成.这个动作会比所有的Servlet都要早. 7.举例.你可能想在项目启动之前就打开数据库. 8.这个监听是自己写的一个类,除了初始化方法,它还有销毁方法.用于关闭应用前释放资源.比如说数据库连接的关闭. https://www.cnblogs.com/xuyuanjia/p/5847790.html 由上面的初始化过程可知容器对于web.xml的加载过程是context-param >> listener >> fileter >> servlet
如果我们有配置ContextLoaderListener, Spring会去web.xml中看我们是否有定义contextConfigLocation这个参数,如果有则Spring容器(Bean工厂)会把定义在该xml文件中的bean加载到容器中,那如果没有定义contextConfigLocation参数,Spring容器会到一个约定的地方去找该文件[源码存在于XmlWebApplicationContext.]
在springmvc这个框架中,一般spring默认存在两个配置文件,一个是applicationContext.xml,另一个是spring-servlet.xml。一般情况下,我们会把注解中的自动加载,定时器的自动加载等内容写在spring-servlet.xml。
然后把spring-servlet.xml,放在web.xml文件下的servlet中进行初始化。(<servlet><init-param><param-name>) 而将applicationContext.xml配置成全局的形式(<context-param><param-name>contextConfigLocation</param-name> 注: spring框架在加载web配置文件的时候。首先加载的是context-param配置的内容,而并不会去初始化servlet。只有进行了网站的跳转,经过了DispatcherServlet的导航的时候,才会初始化servlet,从而加载init-param中的内容。 |
详解contextConfigLocation|Spring启动过程详解
[部分源码分析] https://blog.csdn.net/weixin_36344031/article/details/83419784 过程全分析 https://blog.csdn.net/yilaguandemei/article/details/79589729 org.springframework.web.context.ContextLoaderListener类型是springframework中的原始加载上下文的监听器,通常我们会自定义一个Listener去继承ContextLoaderListener并另外实现我们需要初始化的接口(通常我们会选择实现一些接口来对session的管理) 当监听器设置好了之后 ,启动web容器 监听器开始启动ContextLoaderListener类中的方法contextInitialized() 方法中有下面的语句 ,就会借助容器的上下文去初始一个spring的应用上下文,使用到了ContextLoader这个类 ContextLoader初始化时可以看到一块static代码 : 属性文件中这样定义----引用----> 这样我们就能根据属性文件中的定义反射出一个XmlWebApplicationContext上下文了 接着在XmlWebApplicationContext中看到默认加载spring文件的启动位置 之后再看ContextLoader类,我们就会看到传说中的参数contextConfigLocation 而XmlWebApplicationContext对象正是调用了这个参数去设置启动位置 再看XmlWebApplicationContext继承的AbstractRefreshableConfigApplicationContext类中的setConfigLocation方法将此抽象类中的String[] configLocations值填充 ,在AbstractRefreshableConfigApplicationContext类中支持spring对默认启动文件位置和配置启动文件位置
spring学习-ApplicationContext-spring上下文深入理解 创建Spring容器实例时,必须提供Spring容器管理的Bean的详细配置信息。Spring的配置信息通常采用xml配置文件来设置 , XML配置文件通常使用Resource对象传入。Resource接口是Spring提供的资源访问接口,通过使用该接口,Spring能够以简单、透明的方式访问磁盘、类路径以及网络上的资源。 对于Java EE应用而言,可在启动Web应用时自动加载ApplicationContext实例,接受Spring管理的Bean无须知道ApplicationContext的存在。 开发者只要在web.xml文件中配置一个Listener,该Listener将会负责初始化Spring容器。在这种情况下,容器中Bean处于容器管理下,无须主动访问容器,只需要接受容器的注入管理即可。同时Bean实例的依赖关系通常也是由容器注入,无须Bean实例主动请求。
|
springmvc配置文件
IOC
IoC (DI是对IoC更准确的描述:由容器动态的将某种依赖关系注入到组件中,实现原理:通过反射创建实例;容器加载过程:创建配置文件的抽象资源,beanfactory,把BeanDefinitionReader配置给beanfactory)
在IOC容器中配置bean:
使用标签来将一个类配置到IOC容器
获取IOC容器:
Spring提供两种IOC容器:
- ApplicationContext容器 (ApplicationContext接口,可以代表spring容器,是生产及管理bean的工厂)
- BeanFactory容器(已废弃)
获取ApplicationContext容器:
/**
* ApplicationContext代表IOC容器
* ClassPathXmlApplicationContext从类路径下读取配置文件
* FileSystemXmlApplicationContext从文件系统路径下读取配置文件
* WebXmlApplicationContext:在web 应用程序的范围内加载在 XML 文件中已被定义的 bean。
*/
ApplicationContext context = new FileSystemXmlApplicationContext("config/beans.xml") ;
从IOC容器中获取bean的三种方式
bean的属性注入两种方式
<!-- ref:引用其他已配置的bean -->
以上参考 https://blog.csdn.net/u013634252/article/details/80946404 [棒]
<!-- 开启注解的扫描。到配置的包里面扫描类、方法、属性上面是否有注解 -->
<context:component-scan base-package="cn.itcast"></context:component-scan>
注意:也可以这样开启注解扫描,如下:
<context:annotation-config></context:annotation-config>
但是这种开启注解扫描的方式,只会扫描属性上面的注解。实际开发中用到的并不多!故不推荐使用。
作用在类上@Component:
@Repository
:用于对DAO实现类进行标注(持久层)。@Service
:用于对Service实现类进行标注(业务层)。@Controller
:用于对Controller实现类进行标注(WEB层)。
后三个注解是Spring中提供的@Component
的三个衍生注解(功能目前来讲是一样的),它们是为了让标注类本身的用途更清晰
bean的作用范围的注解:
@Scope
- singleton:单例,默认值
- prototype:多例
根据经验,对有状态的Bean应使用prototype作用域,而对无状态的Bean则应该使用singleton作用
AOP
面向切面编程 将交叉业务封装成切面类 植入到目标业务逻辑中去
Spring提供的AOP,利用AOP实现系统的日志管理功能
实现的大致思路是: 1.前期准备,设计日志表和日志类,编写日志Dao和Service以及实现 2.自定义注解,注解中加入几个属性,属性可以标识操作的类型(方法是做什么的) 3.编写切面,切点表达式使用上面的注解直接定位到使用注解的方法, 4.编写通知,通过定位到方法,获取上面的注解以及注解的属性,然后从session中直接获取或者从数据库获取当前登录用户的信息,最后根据业务处理一些日志信息之后调用日志Service存储日志。 |
https://www.jianshu.com/p/a6ba33da545b 参考 spring 配置扫描切面,开启@AspectJ注解的支持 继承统一的ContentGenerator类,便于共享一些常量。 https://blog.csdn.net/hanruikai/article/details/79315766 含有非注解方式 1.日志表@Table(name = "t_log") 日志类 Dao (Log.java<....private String content;> public interface LogRepository extends JpaRepository<Log, Integer>) Service及实例 /** 定义一个方法,用于声明切入点表达式,方法中一般不需要添加其他代码 * 使用@Pointcut声明切入点表达式 * 后面的通知直接使用方法名来引用当前的切点表达式;如果是其他类使用,加上包名即可 */ 2.自定义注解? 3.切面 配置注解定位方法 4.方法增强 调用service存储日志 以后可以参考写 https://www.cnblogs.com/parryyang/p/5881523.html
JpaRepository支持接口规范方法名查询。意思是如果在接口中定义的查询方法符合它的命名规则,就可以不用写实现, JpaRepository继承自PagingAndSortingRepository接口,JpaRepository基于JPA的Repository接口,极大减少了JPA作为数据访问的代码,JpaRepository是实现Spring Data JPA技术访问数据库的关键接口。 Spring Data(提供了一整套数据访问层(DAO)的解决方案,致力于减少数据访问层(DAO)的开发量。它使用一个叫作Repository的接口类为基础,它被定义为访问底层数据模型的超级接口。)给我们提供几个Repository(类似于我们通常所说的DAO数据访问层),基础的Repository提供了最基本的数据访问功能,其几个子接口则扩展了一些功能。它们的继承关系如下:
|
spring声明式事务实现原理: 主要得益于springMVC+AOP,使用一个事务拦截器,在方法调用的前后/周围进行事务增强(advice),来驱动事务完成.
AOP(实现原理:动态代理JDKProxy &cglibProxy两者区别,Spring的AOP是cglibProxy实现--两者区别:JDK动态代理只能用于带接口的,CGLIB带不带接口都行),只有public方法上的事务注解才起作用,而且必须在代理类外部调用才行~
Spring事务管理的亮点在于声明式事务管理,Spring允许通过声明的方式,在IoC配置中指定事务的边界和事务属性,Spring会自动在指定的事务边界上应用事务属性。 spring将事务管理委托底层具体的持久化实现框架去完成,因此针对不同的框架spring有的不同的接口实现类. 要实现事务管理,首先要在Spring中配置好相应的事务管理器,为事务管理器指定数据资源及一些其他事务管理控制属性。--> -->Spring JDBC 和MybBatis都是基于数据源的Connection访问数据库,所以都可以使用DataSourceTransactionManager
Spring将JDBC的Connection、Hibernate的Session等访问数据库的连接或者会话对象统称为资源,这些资源在同一时刻是不能多线程共享的。为了让DAO、Service类可能做到singleton, Spring的事务同步管理类org.springframework.transaction.support.TransactionSynchronizationManager使用ThreadLocal为不同事务线程提供了独立的资源副本,同时维护事务配置的属性和运行状态信息。事务同步管理器是Spring事务管理的基石,不管用户使用的是编程式事务管理,还是声明式事务管理,都离不开事务同步管理器。Spring框架为不同的持久化技术提供了一套从TransactionSynchronizationManager中获取对应线程绑定资源的工具类 |
*Spring 如何管理事务?(抽象层的三个接口:PlatformTransactionManager,TransactionDefinition,TransactionStatus)
PlatformTransactionManager根据TransactionDefinition提供的事务属性配置信息,创建事务,并用TransactionStatus描述这个激活事务的状态。[TransactionStatus接口可以让事务管理器控制事务的执行,可以检查事务是不是一个新事务,或者是否只读。TransactionStatus还可以初始化回滚操作]
切面(Aepect):横切关注点(跨越应用程序多个模块的功能)被模块化的对象; 通知(Advice):切面必须要完成的工作; ---->增强: 其中一个为ThransactionInterceptor ,它实现了advice接口,包含了把事务加进去的逻辑,也就是事务增强 目标(Target):被通知的对象; 代理(Proxy):像目标对象应用通知之后创建的对象; 连接点(Joinpoint):程序执行的某个特殊位置,如类某个方法调用前、调用后、方法抛出异常后等。连接点由两个信息确定:方法表示的程序执行点;想对点表示的方位。<是一个运行时的概念,只有运行时才存在>-->这里仍然用"源"获取事务属性,这才是真正用于事务. 切点(pointcut):每个类都拥有多个连接点,即连接点是程序类中客观存在的事务;----> TransactionAttributeSource<它是一个源,向外提供东西的意思,TransactionAttribute是事务属性的意思>不是pointcut,但它被pointcut所用,用于检测一个类的方法上是否有@Transaction注解,来确定该方法是否需要加强<TransactionAttributeSourcepointcut用于标识被拦截的方法---是一个静态概念> [整体的意思: pointcut拦截方法,然后使用"源"去方法和类上获取事务属性<用于判断>,如获得则说明方法需要参与事务,进行事务增强] AOP通过切点定位到特定的连接点。 AOP的主要编程对象是切面(aopect),而切面模块化横切关注点。 AOP中 advisor = pointcut + advice savepoint 当执行rollback时,通过指定保存点可以回退到指定的点。注意:这个回退事务,必须是没有commit前使用的; |