前提:
整合就是Mybatis利用Spring提供的类或者注解,创建对象。把对象注入到ioc容器中;
bean是java对象,而java对象不一定是bean对象;
右ioc容器(BeanFactory)生成管理的对象才是bean;
动态代理是Mybatis框架生成的、代理对象不在ioc容器中,所以代理对象无法自动注入到属性中;
我们整合的目的就是把代理对象存放在ioc容器中;
第一步:
//把注册beanDefinition这个类导入到ioc容器中
@Import({RegistrarBeanDefinition.class})
public class Config {
//测试代码
public static void main(String[] args) throws ClassNotFoundException {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
Bean01 user = applicationContext.getBean("bean01", Bean01.class);
user.text();
#一个很重要的类factoryBean:这个类返回的对象会存放在ioc容器中(Spring-Mybatis就是用这个类进行整合的)
//这里没有@Component这个注解,还需要很多步骤
public class UserMapperFactoryBean implements FactoryBean {
//这个class对象就是原来需要执行的那个类
Class aClass;
public UserMapperFactoryBean(Class aClass) {
this.aClass = aClass;
}
@Override
public Object getObject() throws Exception {
//通过动态代理返回一个id为UserMapperFactoryBean 的object对象
//在对象进行执行对象中的方法时,会执行动态代理生成的对象的方法
Object object = Proxy.newProxyInstance(UserMapperFactoryBean.class.getClassLoader(), new Class[]{aClass},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理调用成功");
System.out.println(method.getName());
return 1;
}
});
//返回的这个对象会存入到ioc容器中
return object;
}
@Override
public Class<?> getObjectType() {
//设置返回对象的class类型,在@Autowired这个注解进行ByType注入的时候特别重要
return aClass;
}
}
#ImportBeanDefinitionRegistrar这个接口
spring看到一个类实现了ImportBeanDefinitionRegistrar并且重写了registerBeanDefinitions()方法会直接直接执行这个方法;
这个方法可以用来修改初始化Bean的BeanDefinition;
public class RegistrarBeanDefinition implements ImportBeanDefinitionRegistrar {
//ImportBeanDefinition是用来注册BeanDefinition
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//这个就是我们说手写的MapperScan接口扫描器,扫描我们的mapper接口
//扫描接口的目的就是为了把接口的class对象传入到FactoryBean的构造方法中,用来生成对应的bean对象
MapperScan mapperScan = new MapperScan();
ArrayList<Class> classes = null;
try {
classes = mapperScan.scan(MapperConfig.class);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//进行注册
for (Class cl:classes) {
//通过BeanDefinitionBuilder获取beanDefinition这个属性
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
//指定我们要修改的类的beanDefinition
beanDefinition.setBeanClass(UserMapperFactoryBean.class);
//获取类的构造方法设置构造方法
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(cl);
//把BeanDefinition注册上去,创建Bean对象
registry.registerBeanDefinition(cl.getName(),beanDefinition);
}
}
}
总结:
1.使用@Import注解把用来注册BeanDefinition的类传入到ioc容器中;
2.因为BeanDefinition实现了ImportBeanDefinitionRegistrar这个接口,并且重写了registerBeanDefinitions()这个方法,spring会执行这个方法;
3.registerBeanDefinitions();
这个方法中的registry参数,主要是负责注册BeanDefinition,把注册的BeanDefinition变成Bean对象;
4.我们通过BeanDefinitionFactory来得到BeanDefinition这个参数,把我们需要注册的java类传入,然后就可以设置BeanDefinition参数了(BeanDefinition是通过扫描类或者<bean/>生成的)
5.把设置好的BeanDefinition中注册进BeanDefinitionRegister(BeanDefinitionRegister会执行里面的BeanDefinition生成bean对象)
6.在FactoryBean的实现类中getObject()方法会返回设置好的Bean对象,注册进ioc容器中。在getClass()方法中设置返回的class类型;
#这样子就可以根据传入不同的class对象,返回不同的Bean对象;