Spring-源码-实例化@Mapper

本文介绍下Spring如何实例化Mapper的,中间省去了Mapper如何被扫描到,省去了Mapper转成Db

sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
	@Override
	public Object getObject() throws BeansException {
		try {
			return createBean(beanName, mbd, args);
		}
		catch (BeansException ex) {
			destroySingleton(beanName);
			throw ex;
		}
	}
});
RootBeanDefinition mbd = MapperFactoryBean
//返回是class。org.mybatis.spring.mapper.MapperFactoryBean类型
Class<?> beanClass = mbd.getBeanClass();

疑问:那为什么Mapper在抓成DB的时候也是MapperFactoryBean,但是BeanClass却是UserInfoMapper类型

//mbd.isNonPublicAccessAllowed()返回的是true,执行beanClass.getDeclaredConstructors()方法,所以会拿到的所有构造方法
Constructor<?>[] candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors());

看下MapperFactoryBean的构造方法

public MapperFactoryBean() {
}
public MapperFactoryBean(Class<T> mapperInterface) {
    this.mapperInterface = mapperInterface;
}

最终只取了有参的构造方法

Constructor<?> constructorToUse = 通过从candidates集合里面找到带有参数的构造方法

constructorToUse也就是带有参数的构造方法,通过newInstance就可以得到实例对象了。这个都是基于反射创建对象的,关于Constructor可以看我我的另一篇文章反射实例化对象

//这里得到也只是实例化MapperFactoryBean,不是UserInfoMapper
Object beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);

最后会把上面得到的MapperFactoryBean实例对象转成BeanWrapperImpl,关于BeanWrapper的知识可以看我的另一篇文章BeanWrapper作用,这里的东西都有连贯性,BeanWrapper主要是为了方便修改实例对象MapperFactoryBean里面的属性,包含MapperFactoryBean继承的父类属性。

BeanWrapperImpl bw = new BeanWrapperImpl();
bw.setBeanInstance(beanInstance);
return bw;

上面已经得到了BeanWrapper,切确的是关于MapperFactoryBean类型相关的BeanWrapper,下面开始执行给MapperFactoryBean实例对象里面的属性赋值,这里就要通过BeanWrapper类来完成了

//BeanWrapper instanceWrapper = 上面得到的BeanWrapper对象
//RootBeanDefinition mbd = MapperFactoryBean
//String beanName = userInfoMapper也就我们的实际Mapper名称

//初始化instanceWrapper里面设置的MapperFactoryBean实例的属性
populateBean(beanName, mbd, instanceWrapper);

MapperFactoryBean有很多个属性,会每个属性都有set和get方法,依次执行对应属性的set方法,来给属性赋值,这里重点说一下SqlSessionFactory属性,为什么先看下SqlSessionFactory属性的set方法

private SqlSession sqlSession;

public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
	if (!this.externalSqlSession) {
		//里面有个很重要的SqlSessionTemplate
        this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
    }
}

但是你会发现MapperFactoryBean没有属性SqlSessionFactory,只是有对应的setSqlSessionFactory方法,那Spring是通过什么机制去触发setSqlSessionFactory方法的,原因很简单,setSqlSessionFactory方法上面带有了下面注解,只是编辑器反编译过来没有显示而已,为什么触发setSqlSessionFactory我当初找了半天也不知道

@Autowired
@Qualifier("sqlSessionFactory")

在设置属性的时候,最终会调用下面代码,关于通过MutablePropertyValues设置属性

bw.setPropertyValues(new MutablePropertyValues(deepCopy));
//BeanWrapper bw = 上面代码传过来的对象
//List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
//deepCopy是通过属性遍历处理好的set方法名和属性值,这里不做过多的阐释

最终就是通过上面代码的方式调用了MapperBeanFactory里面属性的set方法,达到调用带有@Autowired注解的方法

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

信仰_273993243

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值