济南达内的老师提醒大家特别注意:
Spring MVC的Controller不是线程安全的!!!
Spring MVC 是基于方法的拦截,粒度更细,而Spring的Controller默认是Singleton的,即:每个request请求,系统都会用同一个Controller去处理,
Spring MVC和Servlet都是方法级别的线程安全,如果单例的Controller或Servlet中存在实例变量,都是线程不安全的,而Struts2确实是线程安全的
优点:不用每次创建Controller,减少了对象创建和销毁
缺点:Controller是单例的,Controller里面的变量线程不安全
解决方案:
1.在Controller中使用ThreadLocal变量,把不安全的变量封装进ThreadLocal,使用ThreadLocal来保存类变量,将类变量保存在线程的变量域中,让不同的请求隔离开来
2.声明Controller为原型 scope="prototype",每个请求都创建新的Controller
3.Controller中不使用实例变量
Spring 事务管理的使用和原理?事务的传播属性
声明式事务管理,在Service之上或Service的方法之上,添加 @Transactional注解
@Transactional如何工作?
Spring在启动时,会去解析生成相关的Bean,这是会查看拥有相关注解的类和方法,并且为这些类和方法生成代理,并根据 @Transactional的相关参数进行相关配置注入,这样就在代理中把相关的事务处理掉了(开启正常提交事务,异常回滚事务)真正的数据库层,事务提交和回滚是通过binlog和redo log实现的
Spring如何解决对象的循环依赖引用?( 只支持Singleton作用域的, setter方式的循环依赖!不支持构造器方式和prototype的循环依赖)
原理:
创建Bean A时,先通过无参构造器创建一个A实例,此时属性都是空的,但对象引用已经创建创建出来,然后把Bean A的引用提前暴露出来,
然后setter B属性时,创建B对象,此时同样通过无参构造器,构造一个B对象的引用,并将B对象引用暴露出来.
接着B执行setter方法,去池中找到A(因为此时,A已经暴露出来,有指向该对象的引用了),这样依赖B就构造完成,也初始化完成,然后A接着初始化完成,循环依赖就这么解决了!
总结:先创建对象引用,再通过setter()方式,给属性赋值,层层创建对象 !!!
Bean A初始化时,先对其依赖B进行初始化,同时,通过默认无参构造器,生成自己的引用,而不调用其setter()方法,
当B对象创建时,如果还依赖C,则也通过无参构造器,生成B的引用,
C对象创建时,如果引用了A,则去对象池中查到A的引用,然后调用setter()方式,注入A,完成C对象的创建
C创建完成后,B使用setter()方式,注入C,完成B对象创建,
B对象场景完成后,A使用setter()方式,注入B,完成A对象创建,
最终,完成setter()方式的循环依赖!
一线互联网公司Java高级面试题总结!
数据库
InnoDB和MyISAM区别和选择
1.InnoDB不支持FULLTEXT类型的索引.
2.InnoDB 中不保存表的具体行数,也就是说,执行select count() from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可.注意的是,当count()语句包含 where条件时,两种表的操作是一样的.
3.对于AUTO_INCREMENT类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引.
4.DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除.
5.LOAD TABLE FROM MASTER操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用.
以上就是济南达内给大家做的内容详解,更多关于java知识的学习,请继续关注济南达内