java常见面试题

Spring面试,IoC和AOP的理解

spring 的优点?
1.降低了组件之间的耦合性,实现了软件各层之间的解耦 
2.可以使用容易提供的众多服务,如事务管理,消息服务等 
3.容器提供单例模式支持 
4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能 
5.容器提供了众多的辅助类,能加快应用的开发 
6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等 
7.spring属于低侵入式设计,代码的污染极低 
8.独立于各种应用服务器 
9.spring的DI机制降低了业务对象替换的复杂性 
10.Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可以自由选择spring的部分或全部 

什么是DI机制? 
依赖注入(Dependecy Injection)和控制反转(Inversion of Control)是同一个概念,具体的讲:当某个角色 
需要另外一个角色协助的时候,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在spring中 
创建被调用者的工作不再由调用者来完成,因此称为控制反转。创建被调用者的工作由spring来完成,然后注入调用者 
因此也称为依赖注入。 
spring以动态灵活的方式来管理对象, 注入的两种方式,设置注入和构造注入。 
设置注入的优点:直观,自然 
构造注入的优点:可以在构造器中决定依赖关系的顺序。 

什么是AOP 
面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面 
1.面向切面编程提供声明式事务管理 
2.spring支持用户自定义的切面 

面向切面编程(aop)是对面向对象编程(oop)的补充, 
面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。 
AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象, 
是对应用执行过程中的步骤进行抽象,,从而获得步骤之间的逻辑划分。 

aop框架具有的两个特征: 
1.各个步骤之间的良好隔离性 
2.源代码无关性 

 java 有内存泄露没?

在语法级别上其实没有,你不用去回收内存,内存自动被垃圾回收器回收了。但是写程序的时候,你调用了一些资源,如连接池或者打开一个文件(io),你打开了必须关闭,垃圾回收器不会自动收集,会造成内存泄露。

Java中的内存泄露当然是指:存在无用但是垃圾回收器无法回收的对象。而且即使有内存泄露问题存在,也不一定会表现出来。 

    Java的一个重要优点就是通过垃圾收集器(GarbageCollection,GC)自动管理内存的回收,程序员不需要通过调用函数来释放内存。因此,很多程序员认为Java不存在内存泄漏问题,或者认为即使有内存泄漏也不是程序的责任,而是GC或 JVM的问题。其实,这种想法是不正确的,因为Java也存在内存泄露,但它的表现与C++不同。

    在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是可达的,即在有向图中,存在通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。

简单的说,一个对象没有任何引用,他会被GC;但是如果这个对象一直被引用,就不会被GC,如果你往这个对象添加数据,他就越来越大,就是nusedbut still referenced,就OOM(outofmemeory)了。

Hibernate问题

1     SessoinFactory

a)       用来产生和管理Session

b)       通常情况下每个应用只需要一个SessionFactory

c)       除非要访间多个数据库的情况

d)       关注两个方法即:openSessiongetCurrentsession的区别

                      i.      open session每次都是新的,需要close

                      ii.      getCurrentsession从上下文找,如果有,用旧的,如果没有,建新的

1. 用途,界定事务边界

2. 事务提交自动close

3. 上下文配置可参见xml文件中

       <propertyname="current_session_context_classs">thread</property>

4. current_session_context_class (jta、thread常用 managed、custom.Class少用)

         a) thread 使用connection但数据库连接管理事务

         b)jta (全称javatransaction api)-java分布式事务管理(多数据库访问)

           jta由中间件提供(jbossWebLogic等,tomcat不支持)

 

2        三种状态区别:

a)        transient:内存中一个对象,没ID,缓存中也没有

b)        persistent:内存中有,缓存中有,数据库有(ID)

c)        detached:内存有,缓存没有,数据库有,ID

 

3exists 与in 选哪个?

fromTopic t where not exists (select m.id from Msg m where m.topic.id=t.id)

fromTopic t where not in(select m.id from Msg m where m.topic.id=t.id)

一般都选择exists ,因为exists的执行效率比in高。

 

 4java 有内存泄露没?

在语法级别上其实没有,你不用去回收内存,内存自动被垃圾回收器回收了。但是写程序的时候,你调用了一些资源,如连接池或者打开一个文件(io),你打开了必须关闭,垃圾回收器不会自动收集,会造成内存泄露。

Java中的内存泄露当然是指:存在无用但是垃圾回收器无法回收的对象。而且即使有内存泄露问题存在,也不一定会表现出来。 

    Java的一个重要优点就是通过垃圾收集器(GarbageCollection,GC)自动管理内存的回收,程序员不需要通过调用函数来释放内存。因此,很多程序员认为Java不存在内存泄漏问题,或者认为即使有内存泄漏也不是程序的责任,而是GC或 JVM的问题。其实,这种想法是不正确的,因为Java也存在内存泄露,但它的表现与C++不同。

    在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是可达的,即在有向图中,存在通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。

简单的说,一个对象没有任何引用,他会被GC;但是如果这个对象一直被引用,就不会被GC,如果你往这个对象添加数据,他就越来越大,就是nusedbut still referenced,就OOM(outofmemeory)了。

 5hibernate 中什么是1+N问题?

在Session的缓存中存放的是相互关联的对象图。默认情况下,当Hibernate从数据库中加载Customer对象时,会同时加载所有关联的Order对象(典型的ManyToOne)。以Customer和Order类为例,假定ORDERS表的CUSTOMER_ID外键允许为null,图1列出了CUSTOMERS表和ORDERS表中的记录。



以下Session的find()方法用于到数据库中检索所有的Customer对象:

List customerLists=session.find("from Customer as c");

运行以上find()方法时,Hibernate将先查询CUSTOMERS表中所有的记录,然后根据每条记录的ID,到ORDERS表中查询有参照关系的记录,Hibernate将依次执行以下select语句:

select * from CUSTOMERS; 
select * from ORDERS where CUSTOMER_ID=1;
select * from ORDERS where CUSTOMER_ID=2;
select * from ORDERS where CUSTOMER_ID=3;
select * from ORDERS where CUSTOMER_ID=4;

通过以上5条select语句,Hibernate最后加载了4个Customer对象和5个Order对象,在内存中形成了一幅关联的对象图,参见图2。



Hibernate在检索与Customer关联的Order对象时,使用了默认的立即检索策略。这种检索策略存在两大不足:

(1) select语句的数目太多,需要频繁的访问数据库,会影响检索性能。如果需要查询n个Customer对象,那么必须执行n+1次select查询语句。这就是经典的n+1次select查询问题。这种检索策略没有利用SQL的连接查询功能,例如以上5条select语句完全可以通过以下1条select语句来完成:

select * from CUSTOMERS left outer join ORDERS 
on CUSTOMERS.ID=ORDERS.CUSTOMER_ID 

以上select语句使用了SQL的左外连接查询功能,能够在一条select语句中查询出CUSTOMERS表的所有记录,以及匹配的ORDERS表的记录。

(2)在应用逻辑只需要访问Customer对象,而不需要访问Order对象的场合,加载Order对象完全是多余的操作,这些多余的Order对象白白浪费了许多内存空间。
为了解决以上问题,Hibernate提供了其他两种检索策略:延迟检索策略和迫切左外连接检索策略。延迟检索策略能避免多余加载应用程序不需要访问的关联对象,迫切左外连接检索策略则充分利用了SQL的外连接查询功能,能够减少select语句的数目。

 

解决办法:

a)        @ManyToOne(fetch=FetchType.LAZY)

      //fetch=FetchType.LAZY 解决N+1问题 说明如下:

      //当多对一(@ManyToOne)已经设定属性"fetch=FetchType.LAZY "时

      //只有当需要时(如:t.getCategory().getName()时)才会去获取关联表中数据 可以解决N+1问题

b)        @BatchSize

      //@BatchSize 解决N+1问题 说明如下:

      //在与查询表(此例中为Topic类)关联的表类(此例中为Category类)头处加@BatchSize(size=5)

      //表示每次可查出5条记录 从而减少了select语句的个数

c)        join fetch

      //join fetch 解决N+1问题 说明如下:

      //修改hql语句为--" from Topic t left join fetch t.category c  "

d)        QBC

      //QBC(Query By Criteria) 解决N+1问题 说明如下:

      //使用QBC的createCriteria(*.class)执行查询 也可避免N+1问题

 

 6     list和iterate的区别

a)        list取所有

b)        iterate先取ID,等用到的时候再根据ID来取对象

c)        session中list第二次发出,仍会到数据库査询

d)        iterate 第二次,首先找session级缓存

 

7.    一级缓存和二级缓存和査询缓存

a)        什么是缓存

                     缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能。

b)        什么是一级缓存,session级别的缓存

c)        I什么是二级缓存,SessionFactory级别的缓存,可以跨越session存在

                     i.        经常被访间

                     ii.        改动不大不会经常改动

                    iii.        数重有限

d)        打开二级缓存

                     i.        hibernate.cfg.xml 设定:

<property

name="cache.use_second_level_cache">true</property>

<property

name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

                 ii.        @Cache注解(由hibernate扩展提供)

@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)

 

注:使用EhCache二级缓存 需要导入ehcache-1.2.3.jar及commons-logging-1.0.4.jar包

e)        load默认使用二级缓存,iterate默认使用二级缓存

f)        list默认往二级缓存加数据,但是查询的时候不使用

g)        如果要query用二级缓存,需打开查询缓存

<propertyname="cache.use_query_cache">true</property>

调用Query的setCachable(true)方法指明使用二级缓存

例如:session.createQuery("fromCategory").setCacheable(true).list();

h)        缓存算法:

                i.        LRU  LFU  FIFO

                            1.            Least Recently Used –最近很少被使用

                            2.            Least Frequently Used (命中率高低)

                            3.            First In First Out 按顺序替换

                             memoryStoreEvictionPolicy= "LRU" (ehcache.xml中配置)

 

    事务并发处理

         a)        事务:ACID

                      i.      Atomic Consistency Itegrity Durability

                      事务的原子性、一致性、独立性及持久性事务的原子性是指一个事务要么全部执行,要么不执行.也就是说一个事务不可能只执行了一半就停止了.比如你从取款机取钱,这个事务可以分成两个步骤:1划卡,2出钱.不可能划了卡,而钱却没出来.这两步必须同时完成.要么就不完成.事务的一致性是指事务的运行并不改变数据库中数据的一致性.例如,完整性约束了a+b=10,一个事务改变了a,那么b也应该随之改变.事务的独立性是指两个以上的事务不会出现交错执行的状态.因为这样可能会导致数据不一致.事务的持久性是指事务运行成功以后,就系统的更新是永久的.不会无缘无故的回滚

          b)        事务并发时可能出现的问题

                       1.    第一类丢失更新(LostUpdate)

                       2.     dirtyread脏读(读到了另一个事务在处理中还未提交的数据)

                       3.     non-repeatableread 不可重复读(同一个事物里,对同一个数据读两回的值是不一样的)

                      4.     second lost update problem 第二类丢失更新(不可重复读的特殊情况)

                      5.     phantom read 幻读(插入与删除问题,在读数据的时候,插入了或删除了数据,影响了读的结果)

                        (只要考虑2,3,5,其他都是特殊情况)

          c)        数据库的事务隔离机制

                     i.        查看 java.sql.Connection 文档

                      ii.       1:read-uncommitted 2:read-committed 4:repeatableread  8:serializable(数字代表对应值)

                                          为什么取值要使用 1 2 4 8 而不是 1 2 3 4

                                          1=0000  2=0010 4=0100 8=1000(位移计算效率高)

                                1.            只要数据库支持事务,就不可能出现第一类丢失更新

                                 2.            read-uncommitted(允许读取未提交的数据)会出现dirtyread, phantom-read,non-repeatable read 问题

                                 3.            read-commited(读取已提交的数据 项目中一般都使用这个)不会出现dirtyread,因为只有另 一个事务提交才会读出来结果,但仍然会出现

non-repeatableread 和phantom-read 使用read-commited机制可用悲观锁 乐观锁来解决non-repeatableread 和phantom-read问题

                                 4.            repeatableread(事务执行中其他事务无法执行修改或插入操作    较安全)

                                 5.            serializable解决一切问题(顺序执行事务 不并发,实际中很少用,效率低)

                                 乐观锁和悲观锁的前提也就是hibernate.conection.isolation=2 也就是隔离级别为read-committed
                                
悲观锁是依赖数据库中的锁, 而乐观锁是在程序中做处理, 所以乐观锁的效率要高

             d)       设定hibernate的事务隔离级别(使用hibernate.connection.isolation配置取值1、2、4、8)

                          i.       hibernate.connection.isolation = 2(如果不设默认依赖数据库本身的级别)

                        ii.        用悲观锁解决repeatable read的问题(依赖于数据库的锁)

                                  1.            select ... for update

                                  2.             使用另一种load方法--load(xx.class, i , LockMode.Upgrade)

                                              a)     LockMode.None无锁的机制,Transaction结束时,切换到此模式

                                              b)     LockMode.read在査询的时候hibernate会自动获取锁

                                               c)    LockMode.write insert  update hibernate 会自动获取锁

                                              d)     以上3种锁的模式,是hibernate内部使用的(不需要设)

                                              e)     LockMode.UPGRADE_NOWAIT是 ORACLE 支持的锁的方式

              e)       Hibernate(JPA)乐观锁定(ReadCommitted)

                          实体类中增加version属性(数据库也会对应生成该字段,初始值为0),并在其get方法前加

                         @Version注解,则在操作过程中没更新一次该行数据则version值加1,即可在事务提交前判断该数据是否被其他事务修改过.

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值