SpringBoot
AOP切面
对目标类进行增强,生成代理对象。前置增强,后置增强,前后都增强等等,类似拦截器,默认使用的是 jdk动态代理
如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDKProxy,去创建代理对象,而对于没有实现接口的对象,就无法使用JDK Proxy去进行代理了,这时候Spring AOP会使用Cglib生成⼀个被代理对象的子类来作为代理
Bean生命周期
- 解析类得到
BeanDefinition
- 使用
BeanFactoryPostProcessor
对BeanDefinition进行增强,如把${}
占位符换成具体的值 - 实例化对象,设置对象属性
- 回调Aware方法,比如
BeanNameAware
,BeanFactoryAware
- 调用
BeanPostProcessorbefore
方法 - 调用
InitializingBean
类的初始化方法afterPropertiesSet
- 调用
BeanPostProcessorafter
方法,在这里会进行AOP - 把Bean放入map中
- 容器关闭时调用
DisposableBean
中destory()
方法
bean的作用域
- singleton :默认都是单例的(SpringMVC中Controller是单例的)
- prototype : 多例,每次从容器中取或注入bean时就会创建
IOC管理对象和new对象区别
每次new对象增加了对象创建的时间,占用内存
Spring中Bean是否线程安全
不是,Bean默认是单例的,存在多个线程操作同一变量的问题
BeanFactoryPostProcessor和BeanPostProcessor
-
BeanPostProcessor在InitializingBean初始化对象前后进行处理
-
BeanFactoryPostProcessor是在将class对象转变为BeanDefinition对象后,对BeanDefinition进行处理,
举例:BeanDefinition实现类根据beanclass属性(要去实例化的对象的全限定类名cn.ccb.Coder)去实例化对象,可以改变beanclass属性的值,去实例其他对象
javapublic class DkBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { //获取coder的BeanDefinition对象 BeanDefinition coder = beanFactory.getBeanDefinition("coder"); //修改其class coder.setBeanClassName(Manager.class.getName()); } }
设计模式
-
工厂设计模式 : Spring使用工厂模式通过 BeanFactory 、 ApplicationContext 创建 bean 对 象
-
代理设计模式 : Spring AOP 功能的实现
-
单例设计模式 : Spring 中的 Bean 默认都是单例的
Spring事务
实现原理
-
加上@Transactional,就可以开启事务,方法中所有的sql都会在一个事务中执行,统一成功或失败
-
Spring事务使用的是AOP环绕通知,在一个方法上加了@Transactional注解后,Spring会基于这个类生成一个代理对象,会将这个代理对象作为bean,当在使用这个代理对象的方法时,如果这个方法上存在@Transactional注解,那么代理逻 辑会先把事务的自动提交设置为false,然后再去执行原本的业务逻辑方法,如果执行业务逻辑方法没有出现异常,那么代理逻辑中就会将事务进行提交,如果执行业务逻辑方法出现了异常,那么则会将事务进行回滚
隔离级别
控制事务之间影响的程度,多个事务读取同一变量并操作同一变量时会出现先问题,有4个隔离级别
- read uncommitted(读取未提交数据)
- read committed(读取已提交的数据,但不可重复读)
- repeatable read(可重复读,Spring默认)
- serializable(可串行化)
详细见:baijiahao.baidu.com/s?id=171582...
传播行为
多个事务方法相互调用时,用哪个事务,以哪个事务为准,7种隔离级别
(REQUIRED)
REQUIRED:spring 默认传播行为,被调用的方法存在事务就使用自己的事务,如果没有事务,则使用当前的事务
REQUIRES_NEW:无论当前存不存在事务,都创建新事务
如何理解starter
在starter中会定义相应的AutoConfiguration,如RedisAutoConfiguration,MybatisAutoConfiguration,在这些configuration中就定义了要用到的第三方Bean对象,然后在 starter包的META-INF/spring.factories中写入该配置类,SpringBoot的自动配置机制加载这个配置类,完成自动配置
SpringMVC
@RestController 和 @Controller 区别
@RestController = @Controller + @ResponseBody
@Controller一般返回一个view视图,@RestController将对象数据直接以 JSON 形式写⼊Response对象的body中
简述springmvc工作流程
见博客
用户发送的请求会先到DispatcherServlet这个请求分发的控制器,然后会调用HandlerMapping找到能够处理该请求的一系列Handler(就是Controller),然后调用HandlerAdapter处理请求,处理完成请求,返回一个ModelAndView,然后调用视图解析器解析视图,解析完返回一个view视图返回给浏览器
Mybatis
方法不能重载
因为是全限名+方法名的寻找策略 当调用接口方法时,接口全限名+方法名,拼接字符串作为 key 值,从而定位到MappedStatement ,举 例: com.mybatis3.mappers.StudentDao.findStudentById,可以唯⼀找到Xml中namespace 为 com.mybatis3.mappers.StudentDao中的id = findStudentById 的MappedStatement
如何实现sql执行结果和目标对象映射的
-
第⼀种是使⽤
<resultMap>
标签,逐⼀定义列名和对象属性名之间的映射关系 -
第⼆种是使用sql 列的别名功能,比如 T_NAME as name
#{} 和 ${} 区别
#{}
是预编译处理、是占位符, ${}是字符串替换、是拼接符#{}
添加参数时值的两边有''
,${}
添加参数时值两边没有''
,有sql
注入风险
${}导致sql
注入的情况
java
select * from user where account = 122221122 and password = 12252152521 or 1=1
#{}防止sql
注入的情况
java
select * from user where account = 122221122 and password = '12252152521 or 1=1'