2018年7月10面试经历

刚进去感觉有点紧张,开始问问题以后就不紧张了0.0。

面试为:

          1.讲一个自己做的项目

          2.对spring的理解

1.首先Spring是一个开源的框架,Spring为简化企业级应用开发而生,使用Spring可以使简单的JavaBean实现以前只有EJB才能实现的功能。Spring是一个IOC和AOP容器框架。
在java开发领域,Spring相对于EJB来说是一种轻量级的,非侵入性的Java开发框架。
Spring主要核心是:
(1).控制反转(IOC):以前传统的java开发模式中,当需要一个对象时我们,我们会自己使用new或者getInstance等直接或者间接调用构造方法创建一个对象,而在Spring开发模式中,Spring容器使用了工厂模式为我们创建了所需要的对象,我们使用时不需要自己去创建,直接调用Spring为我们提供的对象即可,这就是控制反转的思想。实例化一个java对象有三种方式:使用类构造器,使用静态工厂方法,使用实例工厂方法,当使用spring时我们就不需要关心通过何种方式实例化一个对象,spring通过控制反转机制自动为我们实例化一个对象。
(2).依赖注入(DI):Spring使用java Bean对象的Set方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程就是依赖注入的基本思想。
(3).面向切面编程(AOP):在面向对象编程(OOP)思想中,我们将事物纵向抽象成一个个的对象。而在面向切面编程中,我们将一个个对象某些类似的方面横向抽象成一个切面,对这个切面进行一些如权限验证,事物管理,记录日志等公用操作处理的过程就是面向切面编程的思想。
2.在Spring中,所有管理的对象都是JavaBean对象,而BeanFactory和ApplicationContext就是spring框架的两个 IOC 容器,现在一般使用ApplicationnContext,其不但包含了BeanFactory的作用,同时还进行更多的扩展。

          3.讲解下事物、事物的传播性

          答:1.事物是一系列紧密的操作要么都失败要么都成功具有原子性、一致性、隔离、持久性。

                 2.spring支持编程式事物和声明式事物管理两种方式:

                   2.1.声明式事物是基于aop的,只需要在配置文件中配置相应的事物规则(或者加注解@Transaction),本质就是                           方法前后进行拦截,在方法开始之前创建一个事物或者加入一个事物,执行完根据情况提交或者回滚事物。                                 不 足点是只能细化到方法级别,好处就是方便不用手动管理事物。

                   2.2.编程式事物                                                                                                                                                                      3. @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果你在 protected、                            private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常原因是本质AOP的                       动态代理决定的。                                                                                                                                                                            4.传播性               

                       1、REQUIRED(默认模式):业务方法需要在一个容器里运行。如果方法运行时,已经处在一个事务中,那么加入                               到这个事务,否则自己新建一个新的事务。      

                       2、NOT_SUPPORTED:声明方法不需要事务。如果方法没有关联到一个事务,容器不会为他开启事务,如果                                   方法在一个事务中被调用,该事务会被挂起,调用结束后,原先的事务会恢复执行。                

                       3、REQUIRESNEW:不管是否存在事务,该方法总汇为自己发起一个新的事务。如果方法已经运行在一个事务                                中,则原有事务挂起,新的事务被创建。

                       4、 MANDATORY:该方法只能在一个已经存在的事务中执行,业务方法不能发起自己的事务。如果在没有事务                                  的环境下被调用,容器抛出例外。

                      5、SUPPORTS:该方法在某个事务范围内被调用,则方法成为该事务的一部分。如果方法在该事务范围外被调                                 用,该方法就在没有事务的环境下执行。

                     6、NEVER:该方法绝对不能在事务范围内执行。如果在就抛例外。只有该方法没有关联到任何事务,才正常执                                 行。

                     7、NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性·                          执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务                                     造成 影  响。它只对 DataSourceTransactionManager事务管理器起效。

             5。隔离级别

                      1.数据库事务的隔离级别有4种,由低到高分别为Read uncommitted 、Read committed 、Repeatable read 、                                Serializable 。而且,在事务的并发操作中可能会出现脏读,不可重复读,幻读。

                        Read uncommitted

                        读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。

                        事例:老板要给程序员发工资,程序员的工资是3.6万/月。但是发工资时老板不小心按错了数字,按成3.9万/月,                                   该钱已经打到程序员的户口,但是事务还没有提交,就在这时,程序员去查看自己这个月的工资,发现比                                   往常多了3千元,以为涨工资了非常高兴。但是老板及时发现了不对,马上回滚差点就提交了的事务,将数                                   字改成3.6万再提交。

                       分析:实际程序员这个月的工资还是3.6万,但是程序员看到的是3.9万。他看到的是老板还没提交事务时的数据。                                   这就是脏读


                        那怎么解决脏读呢?Read committed!读提交,能解决脏读问题。


                        Read committed

                        读提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。

                        事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(程序员事务开启),收费系统事先                                   检测到他的卡里有3.6万,就在这个时候!!程序员的妻子要把钱全部转出充当家用,并提交。当收费系统                                   准备扣款时,再检测卡里的金额,发现已经没钱了(第二次检测金额当然要等待妻子转出金额事务提交完                                    )。程序员就会很郁闷,明明卡里是有钱的…

                        分析:这就是读提交,若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交                                    后才能读取数据,可以解决脏读问题。但在这个事例中,出现了一个事务范围内两个相同的查询却返回了                                    不同数据,这就是不可重复读


                         那怎么解决可能的不可重复读问题?Repeatable read !


                          Repeatable read

                         重复读,就是在开始读取数据(事务开启)时,不再允许修改操作

                         事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(事务开启,不允许其他事务的UPD                                    ATE修改操作    ),收费系统事先检测到他的卡里有3.6万。这个时候他的妻子不能转出金额了。接下来收                                    费系统就可以扣款了。

                         分析:重复读可以解决不可重复读问题。写到这里,应该明白的一点就是,不可重复读对应的是修改,即UPDAT                                    E操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作


                        什么时候会出现幻读?

                        事例:程序员某一天去消费,花了2千元,然后他的妻子去查看他今天的消费记录(全表扫描FTS,妻子事务开                                        启),看到确实是花了2千元,就在这个时候,程序员花了1万买了一部电脑,即新增INSERT了一条消费                                    记录,并提交。当妻子打印程序员的消费记录清单时(妻子事务提交),发现花了1.2万元,似乎出现了幻                                    觉,这 就是幻读。


                       那怎么解决幻读问题?Serializable!


                      Serializable 序列化

                     Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是                     这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

          4.一个接口有多个实现类,怎么调用。(从事物问题跳这儿来当时有点蒙 没太理解到问题是啥)                                                    1.只需要  接口A =new 实现类B     A.方法   就可以调用  B的方法了                                                                                          2.在spring中: 比如service层    需要在@Service注解中取名 如@Service("dome") 

                2.1在控制层注入的时候确定需要注入那个实现类: @Autowired 下面加一句 @Qualifier("dome")                                            2.2如果有其它的service用到实现类时没用@Resource,要把所有使用到实现类的注解由@Autowired改为                                   @Resource。

          5.list集合对象去重

             Set<Student> ts = new HashSet<Student>();  
              ts.addAll(list);  
              for (Student s : ts) {  
                  System.out.println(student.getName());  

              } 

          6.list集合对象 根据对象属性排序

          7.map 打印全部 key和 value

            for(Map.Entry<String, Object> entry:map.entrySet()){
                    System.out.println("key:"+entry.getKey()+","+"value:"+entry.getValue());
               }

       

猜你喜欢

转载自blog.csdn.net/u013208718/article/details/80990360