Bean 的配置方式:
通过全类名(反射) 通过工厂方法(静态工厂方法 & 实例工厂方法) FactoryBeanFactoryBean定义
package org.springframework.beans.factory; public interface FactoryBean<T> { T getObject() throws Exception; Class<?> getObjectType(); boolean isSingleton(); }FactoryBean 通常是用来创建比较复杂的bean,一般的bean 直接用xml配置即可, 但如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,用xml配置比较困难,这时可以考虑用FactoryBean。
在整个 Spring MVC 框架中, DispatcherServlet 处于核心位置,负 责协调和组织不同组件以完成请求处理并返回响应的工作。
SpringMVC 处理请求过程:
1、若一个请求匹配 DispatcherServlet 的请求映射路径(在 web.xml 中指定), WEB 容器将该请求转交给 DispatcherServlet 处理。2、DispatcherServlet 接收到请求后, 将根据请求信息(包括 URL、HTTP 方法、请求头、请求参数、Cookie 等)及 HandlerMapping 的配置找到处理请求的处理器(Handler)。可将 HandlerMapping 看成路由控制器,将 Handler 看成目标主机。3、当 DispatcherServlet 根据 HandlerMapping 得到对应当前请求的Handler 后,通过 HandlerAdapter 对 Handler 进行封装,再以统一的适配器接口调用 Handler。4、处理器完成业务逻辑的处理后将返回一个 ModelAndView 给DispatcherServlet, ModelAndView 包含了视图逻辑名和模型数据信息。5、DispatcherServlet 借助 ViewResoler 完成逻辑视图名到真实视图对象的解析, 得到真实视图对象 View 后, DispatcherServlet 使用这个 View 对ModelAndView 中的模型数据进行视图渲染。@RequestBody
处理HttpEntity传递过来的数据,一般用来处理非Content-Type: application/x-www-form-urlencoded编码格式的数据。 GET请求中,因为没有HttpEntity,所以@RequestBody并不适用。 POST请求中,通过HttpEntity传递的参数,必须要在请求头中声明数据的类型Content-Type,SpringMVC通过使用HandlerAdapter 配置的HttpMessageConverters来解析HttpEntity中的数据,然后绑定到相应的bean上。
@Autowired与@Resource、@Qualifier
@Resource装配顺序
如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配主要区别
@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上。@Autowired默认按类型装配(这个注解是属于spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false。@Resource(这个注解属于J2EE的,是JSR规范定义的注解),默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。 当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。推荐使用:@Resource注解在字段上,这样就不用写setter方法了,并且这个注解是属于J2EE的,减少了与spring的耦合。这样代码看起就比较优雅。@Qualifier一般作为@Autowired()的修饰用,当使用@Autowired注入出现多个Bean的注入异常时,则需要指定注入的Bean的名称。1、SpringBoot自动配置原理
参考
2、SpringCloud Config properties属性加载分析
上 下
3、SpringBoot解决循环依赖
循环依赖的解决
步骤:
1、继承AbstractRoutingDataSource路由 2、ThreadLocal存数据源 3、构建数据源并初始化 4、指定主库 @Primary 5、AOP拦截注解+注解标记方法在对象内部的方法中调用该对象的其他使用AOP机制的方法,被调用方法的AOP注解失效。
在一个类的A方法中调用同类的B方法,实际上使用的是使用实例调用方式this.B(),而代理对象是$开头的一个对象,此时的调用并不会走代理,注解会无效。 因为在被代理对象的方法中调用被代理对象的其他方法时。其实是没有用代理调用,是用了被代理对象本身调用的。
newProxyInstance 产生一个代理对象 ,三个参数
1.classloader 代理对象和被代理对象应该处于同一个 classloader 2.接口产生的代理对象应该实现哪些接口 3.handel 执行代理对象方法时,应用哪个handel 处理。(接口中有什么方法,代理中就有什么方法 代理中的每个方法在调用的时候都会把方法自身传给 handel, 并把代理对象和参数都传递过去 )
静态代理:由程序员或者自动生成工具生成代理类,然后进行代理类的编译和运行。在代理类、委托类运行之前,代理类已经以.class的格式存在。
动态代理:在程序运行时,由反射机制动态创建而成。(各种字节码操纵工具以及框架可以实现)
动态代理设计模式类图
动态代理宏观图
连接ASM部分
补充模糊查询
表达式: name like"%"#{name}"%" #起到占位符的作用表达式: name like '%${name}%' $进行字符串的拼接,直接把传入的值,拼接上去了,没有任何问题表达式: name likeconcat(concat('%',#{username}),'%') 这是使用了cancat进行字符串的连接,同时使用了#进行占位表达式:name like CONCAT('%','${name}','%') 对上面的表达式进行了简化,更方便了SQL注入漏洞测试:原文:http://www.cnblogs.com/leftshine/p/SQLInjection.html#downloadFile
还有很多其他的标签,<resultMap>、<parameterMap>、<sql>、<include>、<selectKey>,加上动态sql的9个标签,trim|where|set|foreach|if|choose|when|otherwise|bind等,其中 <sql> 为sql片段标签, 通过 <include> 标签引入sql片段,<selectKey> 为不支持自增的主键生成策略标签。
Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值, 接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement, 举例:com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace为com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。 在Mybatis中,每一个 <select>、<insert>、<update>、<delete> 标签,都会被解析为一个MappedStatement对象。 Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。 Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。 分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。 举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,10
Mybatis动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能,Mybatis提供了9种动态sql标签trim|where|set|foreach|if|choose|when|otherwise|bind。 其执行原理为,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。
Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。 它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来, 然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。 当然了,不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。
如果我们一般插入数据的话,如果我们想要知道刚刚插入的数据的主键是多少,我们可以通过以下的方式来获取 通过LAST_INSERT_ID()获取刚插入记录的自增主键值,在insert语句执行后,执行select LAST_INSERT_ID()就可以获取自增主键。
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User"> <selectKey keyProperty="id" order="AFTER" resultType="int"> select LAST_INSERT_ID() </selectKey> INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address}) </insert>第一种:使用占位符的思想
在映射文件中使用#{0},#{1}代表传递进来的第几个参数,使用@param注解:来命名参数
第二种:使用Map集合作为参数来装载,根据key自动找到对应Map集合的value
PS:由于一直使用SpringBoot、SpringCloud,对于SSM没有过多研究,主要是根据网络和自己的经历整理的。仅供参考
转自:jxnu-liguobin
https://github.com/jxnu-liguobin/Java-Learning-Summary