Spring FactoryBean 详解


声明:本文转载自https://my.oschina.net/tigerlene/blog/1579893,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

引言

在 mybatis-spring 中,我们会使用 MapperFactoryBean 为我们 的mapper(interface)创建代理类。 SqlSessionFactoryBean 通过dataSource成属性创建对应的sqlSessionFactory。两个接口都实现了Spring FactoryBean interface。所以我们就通过这个来理解一下 Spring FactoryBean.

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">   <property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />   <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean>  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">   <property name="dataSource" ref="dataSource" /> </bean>  

###FactoryBean

> Customizing instantiation logic with a FactoryBean,Implement the org.springframework.beans.factory.FactoryBean interface for objects that are themselves factories.

简介:
first,FactoryBean 是一个扩展点,主要是扩展创建复杂的对象实现。
second, 实现了FactoryBean接口的类自己就是一个factory,可以创建对象。接口一共三个方法,我们重点看一下其中的 getObject();

Object getObject(): returns an instance of the object this factory creates. The instance can possibly be shared, depending on whether this factory returns singletons or prototypes.  boolean isSingleton(): returns true if this FactoryBean returns singletons, false otherwise.  Class getObjectType(): returns the object type returned by the getObject() method or null if the type is not known in advance.  

对照这个过程我们就阅读一下mybatis-spring MapperFactoryBean的源码,这里不再重复,请参考 http://blog.csdn.net/tanqidong1992/article/details/48026491

这里说明一下: sessionSqlTemplate 实现SqlSession, sessionSqlTemplates是线程安全的,所以在FactoryBean getObject的时候就注入了SqlSession,所以完成之后,mapper可以直接使用。

如果不看具体的代理对象生成过程,我们就可以理解了整个对象的创建过程,比如SqlSessionFactoryBean就使用了一个build方法。

FactoryBean 的好处就是简化复杂对象的创建,上面的创建过程绑定了sqlSession,通过代理生成了代理对象,这样使用起来就非常简单了。

###Interface 生成代理对象

现在我们来看下为mapper接口生成代理对象的过程:

public class MapperRegistry {    private Configuration config; // 为每个mapper类型存储一个对应的MapperProxyFactory   private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();    public MapperRegistry(Configuration config) {     this.config = config;   }    @SuppressWarnings("unchecked")   public <T> T getMapper(Class<T> type, SqlSession sqlSession) {     final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);     if (mapperProxyFactory == null)       throw new BindingException("Type " + type + " is not known to the MapperRegistry.");     try {         //我们直接看这部分代码吧       return mapperProxyFactory.newInstance(sqlSession);     } catch (Exception e) {       throw new BindingException("Error getting mapper instance. Cause: " + e, e);     }   } ... }  

MapperProxyFactory

public class MapperProxyFactory<T> {    private final Class<T> mapperInterface;   private Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>();    public MapperProxyFactory(Class<T> mapperInterface) {     this.mapperInterface = mapperInterface;   }    public Class<T> getMapperInterface() {     return mapperInterface;   }    public Map<Method, MapperMethod> getMethodCache() {     return methodCache;   }    @SuppressWarnings("unchecked")   protected T newInstance(MapperProxy<T> mapperProxy) {     return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);   }    public T newInstance(SqlSession sqlSession) {     final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);     return newInstance(mapperProxy);   }  }  

MapperProxy

public class MapperProxy<T> implements InvocationHandler, Serializable {    private static final long serialVersionUID = -6424540398559729838L;   private final SqlSession sqlSession;   private final Class<T> mapperInterface;   private final Map<Method, MapperMethod> methodCache;    public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {     this.sqlSession = sqlSession;     this.mapperInterface = mapperInterface;     this.methodCache = methodCache;   }    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {     if (Object.class.equals(method.getDeclaringClass())) {       try {         return method.invoke(this, args);       } catch (Throwable t) {         throw ExceptionUtil.unwrapThrowable(t);       }     }     final MapperMethod mapperMethod = cachedMapperMethod(method);     return mapperMethod.execute(sqlSession, args);   }    private MapperMethod cachedMapperMethod(Method method) {     MapperMethod mapperMethod = methodCache.get(method);     if (mapperMethod == null) {       mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());       methodCache.put(method, mapperMethod);     }     return mapperMethod;   }  }  

参考: https://www.ibm.com/developerworks/cn/java/j-lo-proxy1/

本文发表于2017年11月26日 12:33
(c)注:本文转载自https://my.oschina.net/tigerlene/blog/1579893,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2101 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1