先上小结:
- Spring标准代理创建流程,this.initializeBean()方法。
- BeanPostProcessor对Mapper代理实例进行预处理。
- 执行MapperFactoryBean.afterPropertiesSet(),从MapperFactoryBean.SqlSessionTemplate.SqlSessionFactory.Configuration.MapperRegistry.knownMappers获得之前创建好的工厂代理,如果没有则重新创建一个。
- 继续Spring标准代理创建流程,准备由MapperFactoryBean工厂代理创建Mapper动态代理。
- 调用MapperFactoryBean.newInstance(),创建MapperProxy,作为Mapper的动态代理。
正文:
在这一篇中,Mapper动态代理可以正式生成了,流程分为两部分:
- 第一部分是前文创建Mapper代理工厂准备工作的后续,其执行结果是创建了Mapper的代理工厂。
- 第二部分是用依赖注入的方式注入Mapper参数,并且正式生成Mapper的动态代理。
第一部分,创建Mapper代理工厂
在之前创建Mapper动态代理的准备工作中,我们看到,在doCreateBean()方法中,重点关注了两个方法:
this.populateBean(beanName, mbd, instanceWrapper);
和他的下一行:
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
在之前的文章中分析了this.populateBean()方法,对Mapper实例进行属性注入,下面来分析一下this.initializeBean()方法,此方法用于生成Mapper的动态代理。
this.initializeBean()方法在AbstractAutowireCapableBeanFactory类中,其中的exposedObject参数就是前面BeanWrapper中预创建的代理实例,方法源码如下:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
方法最开始的:
invokeAwareMethods(beanName, bean);
此方法主要是处理实现类Aware接口的类,此接口是个标注接口,无具体方法。实现了此接口的类在初始化时会调用其setXXX()方法。Mybatis的Mapper没有实现Aware接口,这段忽略。
下面调用的是applyBeanPostProcessorsBeforeInitialization()方法,在这个方法中,会有一堆BeanPostProcessor对代理实例进行预处理:
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
预处理结束后,调用的是invokeInitMethods()方法,此方法主要用于执行代理类的afterPropertiesSet()方法,代码如下:
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
可以看到,其中的
((InitializingBean) bean).afterPropertiesSet();
这一行调用的是bean的afterPropertiesSet()方法,bean的类型是由BeanDefinition决定的,在之前的代码中,BeanDefinition里bean的类型已经从本身的Mapper接口类变成了MapperFactoryBean类,所以此处执行的afterPropertiesSet()方法实际上是MapperFactoryBean类的afterPropertiesSet()方法。
afterPropertiesSet()方法实现在MapperFactoryBean类的父类的父类DaoSupport中,他们的继承关系是:
MapperFactoryBean<T> extends SqlSessionDaoSupport
SqlSessionDaoSupport extends DaoSupport
所以来看一下afterPropertiesSet()方法的代码:
public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {
this.checkDaoConfig();
try {
this.initDao();
} catch (Exception var2) {
throw new BeanInitializationException("Initialization of DAO failed", var2);
}
}
方法首先调用的是this.checkDaoConfig(),实际上这个方法的实现在MapperFactoryBean类中:
protected void checkDaoConfig() {
super.checkDaoConfig();
Assert.notNull(this.mapperInterface, "Property 'mapperInterface' is required");
Configuration configuration = this.getSqlSession().getConfiguration();
if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
try {
configuration.addMapper(this.mapperInterface);
} catch (Exception var6) {
this.logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", var6);
throw new IllegalArgumentException(var6);
} finally {
ErrorContext.instance().reset();
}
}
}
可见,方法先是调用了super.checkDaoConfig()方法,MapperFactoryBean的父类SqlSessionDaoSupport中这个方法只有一句断言:
protected void checkDaoConfig() {
Assert.notNull(this.sqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
}
继续向下看:
Configuration configuration = this.getSqlSession().getConfiguration();
其中getSqlSession()方法就是之前注入好的SqlSessionTemplate对象,而getConfiguration()方法是从SqlSessionTemplate对象中获取sqlSessionFactory对象然后再获取其Configuration对象,也就是这样:
configuration=MapperFactoryBean.SqlSessionTemplate.SqlSessionFactory.Configuration
继续往下:
configuration.hasMapper()方法,configuration对象中维护了一个MapperRegistry类,MapperRegistry类中有一个knownMappers 属性,类型是HashMap<Class<?>, MapperProxyFactory<?>>,用于保存已经加载好的动态代理,其中的key就是Mapper接口类。
在前面创建SqlSessionFactory的过程中,其实已经读取了配置的Mapper.xml文件,并依此生成了很多Mapper接口的代理工厂类,并添加到了knowMappers中,所以当我们要注入被@AutoWired注解的Mapper属性时,基本都可以从knowMappers中拿到其对应的代理工厂类。
如果Configuration中没有这个动态代理,则调用configuration.addMapper()方法添加,而且此代理是添加的时候重新生成的,configuration.addMapper()方法如下:
public <T> void addMapper(Class<T> type) {
mapperRegistry.addMapper(type);
}
然后是mapperRegistry的addMapper()方法:
public <T> void addMapper(Class<T> type) {
if (type.isInterface()) {
if (hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
boolean loadCompleted = false;
try {
knownMappers.put(type, new MapperProxyFactory<T>(type));
// It's important that the type is added before the parser is run
// otherwise the binding may automatically be attempted by the
// mapper parser. If the type is already known, it won't try.
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
parser.parse();
loadCompleted = true;
} finally {
if (!loadCompleted) {
knownMappers.remove(type);
}
}
}
}
以上流程和创建SqlSessionFactory时创建Mapper动态代理的流程基本一样。
至此,我们已经把Mapper的代理工厂准备好了,回到本篇最开始,doCreateBean()方法中
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
这一行的目的就达到了,得到的exposedObject就是Mapper的代理工厂。
接下来有一段关于earlySingletonExposure的判断,执行了很多逻辑,主要目的是为了判断循环依赖时的依赖对象有没有被改变,改变了就抛异常,此处涉及Spring循环依赖的原理。
于是,doCreateBean()方法完成,调用它的createBean()方法完成,我们顺着调用栈回到AbstractBeanFactory的doGetBean()方法,刚刚执行的是
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
其中的getSingleton()方法执行完成,下面执行的是:
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
这行。
注意,虽然此处doGetBean()方法的代码在AbstractBeanFactory类中,但实际执行此方法的是一个DefaultListableBeanFactory实例,他们的继承关系是:
DefaultListableBeanFactory继承AbstractAutowireCapableBeanFactory继承AbstractBeanFactory
所以此处的getObjectForBeanInstance()方法是DefaultListableBeanFactory类的方法,实际的代码实现在其父类AbstractAutowireCapableBeanFactory中:
@Override
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
String currentlyCreatedBean = this.currentlyCreatedBean.get();
if (currentlyCreatedBean != null) {
registerDependentBean(beanName, currentlyCreatedBean);
}
return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
}
其中调用的:
return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
才是执行AbstractBeanFactory中的方法:
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
注意其中这几行:
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
在这个判断中,Mapper的工厂代理会直接返回。
原因如下:第一个条件的结果是false,因为beanInstance确实是MapperFactoryBean(不要忘了前面的叹号),第二个条件的结果是true,BeanFactoryUtils.isFactoryDereference()的代码是这样的:
public static boolean isFactoryDereference(@Nullable String name) {
return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
}
也就是判断name是否是工厂类标识符(&)开头的。
在创建Mapper代理工厂的准备工作这篇文章中,可以知道Spring给所有的BeanDefinition创建代理时,给所有的工厂类名前面都加上了这个工厂类标识符,其中就包括Mapper的代理。
于是我们回到文章最开始的:
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
我们得到的实际上就是Mapper的代理工厂。
第二部分,创建Mapper动态代理
当我们在Service中使用:
@Autowired
private OrderMapper orderMapper;
这种方式使用Mapper接口时,Spring会向Service的代理中注入OrderMapper的代理,也会通过getBean()等方法来创建或获取代理。
Spring检查并发现@Autowired代理的逻辑省略,我们从AbstractBeanFactory的getBean()方法开始看代码:
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
调用doGetBean()方法:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
...
}
...
return (T) bean;
}
此时sharedInstance已经有值了,所以bean通过此行代码获取:
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
注意,虽然此行代码在AbstractBeanFactory类中,但实际调用此代码的是DefaultListableBeanFactory类,他们的继承关系是:
DefaultListableBeanFactory继承AbstractAutowireCapableBeanFactory继承AbstractBeanFactory
getObjectForBeanInstance()方法实现在了AbstractAutowireCapableBeanFactory类中:
@Override
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
String currentlyCreatedBean = this.currentlyCreatedBean.get();
if (currentlyCreatedBean != null) {
registerDependentBean(beanName, currentlyCreatedBean);
}
return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
}
方法最后调用了父类的getObjectForBeanInstance()方法,也就是AbstractBeanFactory的方法:
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
生成Mapper代理工厂的时候就调用过这个方法,当时方法在
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
这一段就返回了,因为beanInstance是FactoryBean,所以第一个条件是true,name是工厂标识符开头的,所以第二个条件也是true。
这次不同了,虽然beanInstance还是FactoryBean,但是name是Mapper类原名,不包含工厂标识符,所以第二个条件是false,代码得以向后执行。
可见,Spring在这个方法中对工厂类和非工厂类进行了不同的处理方案:
- 非工厂类,直接返回之前生成的代理。
- 工厂类,生成代理工厂时,直接返回之前生成的代理。
- 工厂类,需要生成工厂中指定的具体代理时,向后执行,调用getObjectFromFactoryBean()方法。
在方法的最后,代码执行到这一行:
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
getObjectFromFactoryBean()方法在AbstractBeanFactory的父类FactoryBeanRegistrySupport中:
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
}
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
因为MapperFactoryBean都是单例的,第一次创建Mapper代理时缓存中也没有,所以代码一开始会执行到这一行:
object = doGetObjectFromFactoryBean(factory, beanName);
这就是从factory中获得一个具体动态代理的方法,看一下这个方法的代码:
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
代码逻辑比较简单,传入的factory参数就是Mapper的代理工厂MapperFactoryBean,主要关注这一行:
object = factory.getObject();
调用的就是MapperFactoryBean的getObject()方法:
public T getObject() throws Exception {
return this.getSqlSession().getMapper(this.mapperInterface);
}
在此方法中,this.getSqlSession()方法得到的是SqlSessionTemplete,看一下其getMapper()方法:
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
然后是MapperRegistry类的getMapper()方法:
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);
}
}
首先,从knowMappers里面按type获得之前生成的代理工厂实例MapperProxyFactory,然后调用他的newInstance()方法:
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
建立一个MapperProxy实例,其中的mapperInterface参数就是代理工厂实例中记录的Mapper的接口类,这个实例将作为Mapper动态代理的调用处理程序,当我们用此代理调用一个方法时,将调用MapperProxy的invoke()方法。
此方法把这个MapperProxy实例作为参数传给了newInstance()方法:
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
在此方法中最终生成了Mapper的动态代理。这个代理会被Spring的依赖注入机制注入到其他的对象中,从而调用Mapper接口中的各个方法。
(本文结束)