面试整理

设计模式

1)代理模式

对原始类进行功能扩展,但是对外暴漏的接口不变。不改变原始类的功能,只是对功能进行补充。

spring mybatis 中SqlSessionTemplate 代理SqlSession,增加自动事务处理和自动close。

seam 扩展的EntityManager。

实现方式1,使用java.lang.reflect.Proxy.newProxyInstance

Proxy只能对接口生成代理类(动态生成class,比如$proxy13,会根据接口名称缓存,同样的接口只会生成一次class)。

 

public static Object newProxyInstance(ClassLoader loader,
                      Class<?>[] interfaces,
                      InvocationHandler h)

使用方式:创建代理类后直接调用接口的响应方法

this.sqlSessionProxy = (SqlSession) newProxyInstance(xxxClassLoader(),
        new Class[] { SqlSession.class },
        new SqlSessionInterceptor());

sqlSessionProxy.methodxxx(xxx....);

代理类实际生成的代码中有对应的接口方法,比如methodxxx(xxx....),方法体可能的内容是:只是调用

InvocationHandler public Object invoke(Object proxy, Method method, Object[] args)方法,这样就将控制全

移交到了SqlSessionInterceptor中,Object proxy参数就是动态类实例本身($proxy13的实例),一般情况下

不会使用该参数,在方法中能获取到的信息就是SqlSessionInterceptor实例本身和Method method, Object[] args,如何对实例进行代理呢?只能通过SqlSessionInterceptor实例本身获得要代理的原始类实例,通过SqlSessionInterceptor实例的属性构造出代理类实例或者在直接要代理的实例放入SqlSessionInterceptor中

SqlSessionInterceptor的大概实现如下

。。。


sqlSession=xxxx;//创建sqlSession所需的信息由SqlSessionInterceptor实例本身提供

Object result = method.invoke(sqlSession, args);

afterDoSomething(); 

 

下面的示例是在构造代理对象时将要代理的实例放入InvocationHandler中

  1. public class MyProxy {  
  2.     private MyHandler myHandler;  
  3.       
  4.     public void setMyHandler(MyHandler myHandler) {  
  5.         this.myHandler = myHandler;  
  6.     }  
  7.   
  8.     public Object getProxy(Object target){  
  9.         myHandler.setObj(target);  
  10.         return Proxy.newProxyInstance(MyProxy.class.getClassLoader(),   
  11.                                     target.getClass().getInterfaces(),   
  12.                                     myHandler);  
  13.     }  

 

你可能感兴趣的:(面试)