mybatis笔记②——SqlSessionTemplate的自动装配和Mapper的bean的实例化流程

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_35262405/article/details/100826151

spring的自动装配永远都是开启的,只是默认模式是no罢了

spring的自动装配从来都不是在需要注入的地方加上注解,这一点可以从基于xml的方式注入来看出,只需要设置default-autowire属性就够了,默认是no模式
在这里插入图片描述
下面是4种模式的官方解释
在这里插入图片描述
如果是使用非xml方式来配置spring那么就无法设置这个自动装配的模式了,这样就默认是no模式,于是spring提供了注解的方式协助自动装配,在no模式下只要加上例如@Autowired、@Resource注解也可以完成自动装配。

可是我们要记住这种只是no模式下的自动装配,从来不是byType、byName或者constructor模式下的自动装配。

但是我们同样也可以通过javaConfig开启某一个bean的自动装配,示例如下

加入有如下两个bean对象

@Component
public class AutoTest1 {
	private AutoTest2 autoTest2;

	public AutoTest2 getAutoTest2() {
		return autoTest2;
	}

	public void setAutoTest2(AutoTest2 autoTest2) {
		this.autoTest2 = autoTest2;
	}
}
@Component
public class AutoTest2 {
	private AutoTest1 autoTest1;

	public AutoTest1 getAutoTest1() {
		return autoTest1;
	}

	public void setAutoTest1(AutoTest1 autoTest1) {
		this.autoTest1 = autoTest1;
	}
}
public static void main(String[] args) {
	AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
	AutoTest1 autoTest1 = annotationConfigApplicationContext.getBean(AutoTest1.class);
	AutoTest2 autoTest2 = annotationConfigApplicationContext.getBean(AutoTest2.class);
	/**
	 * 如果什么都没设置那么spring的自动装配的模式是no
	 * 自然就得不到对象中的属性
	 */
	System.out.println("autoTest1&&AutoTest2===========>"+autoTest1.getAutoTest2());
	System.out.println("autoTest2&&AutoTest1===========>"+autoTest2.getAutoTest1());
}
autoTest1&&AutoTest2===========>null
autoTest2&&AutoTest1===========>null

这样下来自然得到的是null

但是如果我们通过ImportBeanDefinitionRegistrar接口的实现类改变bd自动装配的模式

public class AutoImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		//拿到gbd
		GenericBeanDefinition autoTest1 = (GenericBeanDefinition) registry.getBeanDefinition("autoTest1");
		//设置gbd的自动装配模式为byType
		autoTest1.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
		//重新注册bd
		registry.registerBeanDefinition("autoTest1",autoTest1);
	}
}

再次运行测试代码我们会发现autoTest1对象中已经完成了自动装配

autoTest1&&AutoTest2===========>com.zdd.spring.AutoDistribution.AutoTest2@105fece7
autoTest2&&AutoTest1===========>null

不过如果我们去掉set方法依然不能自动装配,因为byType模式的自动装配就是通过set方法来实现的(byName也同样需要set方法)

如果是注解就不需要借助set方法


自动装配会忽略的属性

扫描二维码关注公众号,回复: 7608225 查看本文章

这里讨论的是byType模式的自动装配,下面这个方法就是底层判断自动装配的属性是否被忽略,返回的就是真正需要自动装配的方法,传进来的BeanWrapper包含了类的所有属性(包括父类)

protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
	Set<String> result = new TreeSet<>();
	PropertyValues pvs = mbd.getPropertyValues();
	PropertyDescriptor[] pds = bw.getPropertyDescriptors();
	for (PropertyDescriptor pd : pds) {
		if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
				!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
			result.add(pd.getName());
		}
	}
	return StringUtils.toStringArray(result);
}

spring会把一个对象的所有属性(包括父类的)都拿出来判断是否要自动装配,这里的属性是只要有get方法(Boolean类型的get方法是isXXX方法)或者set方法的所有属性。

首先判断有没有set方法,没有就不会自动装配

其次会将设置了被忽略的属性忽略掉,这里忽略的属性可以通过一个接口
在这里插入图片描述
如果在bd中设置了无需自动装配,已经设置了属性值的属性也会被排除
在这里插入图片描述
在这里插入图片描述
最后简单类型也会被排除
在这里插入图片描述
这里包含了六种简单类型
在这里插入图片描述


在mybatis中也是借助了spring的自动装配来将之前所说的SqlSessionTemplate注入到每一个mapperbean中的
在这里插入图片描述
在这里插入图片描述
mybatis在@MapperScan注解中同样也注入了一个MapperScannerRegistrar对象,它也实现了ImportBeanDefinitionRegistrar接口
在这里插入图片描述
mybatis也是在这个方法中将所有MapperFactoryBean的bd的自动装配模式设置为byType的
在这里插入图片描述


Mybatis总结

spring在实例化mapperbean的时候将方法的信息(包括注解)解析出来,并且把这个元数据放到一个map中,key是类全名加方法名。这个map存在sqlsession中,叫做MappedStatments。这样在mapperbean真正执行方法时就可以从其中的sqlSessionTemplate中拿到map,通过类全名加方法名得到元数据,拿到真正的sql语句,从数据库中拿到数据或者修改数据,底层依然是JDBC。

这里需要注意的就是sqlSession的实现类DefaultSqlSession被sqlSessionTemplate封装,并且sqlSessionTemplate被代理,在代理方法中最后非关闭session。

还有就是注入的mapper是MapperFactoryBean,只是返回的是mapper的代理对象。

还有就是在MapperFactroyBean中注入sqlSessionTemplate是使用了spring的自动装配,借助了ImportBeanDefinitionRegistrar接口开启了byType模式的自动装配。无需加上spring的注解注入,这样mybatis的源码就不会被spring的代码侵蚀,减少了耦合度。

猜你喜欢

转载自blog.csdn.net/qq_35262405/article/details/100826151
今日推荐