明白我们需要的是什么
首先,当我们整合二者的时候,是不是一直都只有接口呢,而我们真正调用的是不是这个接口的一个代理类呢,所以我们目的其实就是把这个代理类作为bean给注入到spring容器中,这样我们就可以从容器中拿代理对象,并执行相应的操作。
FactoryBean生成bean(代理对象)
首先我们要知道FactoryBean是一个接口,实现它需要具体实现两个方法,getObject(),getObjectType(),当我们实现它的时候spring启动的时候就会判断有没有实现FactoryBean实现了的话就会调用getObject()方法。那我们就可以在这里做文章,返回一个代理对象(这里其实我们注入一个sqlsessionFactory就可以了,这样返回的就是mybaties的代理对象)给他。先看代码:
@Componentpublic class LubanFactoryBean implements FactoryBean {//这个表示传进来的接口的类型private Class mapperInterface;//通过构造器public LubanFactoryBean(Class mapperInterface) {this.mapperInterface = mapperInterface;}@Overridepublic Object getObject() throws Exception {//这里就使用动态代理Object proxyInstance = Proxy.newProxyInstance(LubanFactoryBean.class.getClassLoader(),//×××××××注意看这里,我这里用的是属性,所以这个自定义FacotoryBean//就变的灵活了new Class[]{mapperInterface.class}, newInvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (Object.class.equals(method.getDeclaringClass())) {return method.invoke(this, args);} else {//执行代理逻辑return null;}}});return proxyInstance;}@Overridepublic Class<?> getObjectType() {return UserMapper.class;}}
FactoryBean由谁调用呢
FactoryBean由谁调用呢,总不可能自己变出来吧,它是由BeanDefinitionRegistrar生成出来的接下来看这段代码
public class LubanImportBeanDefinitionRegistrar implements Import BeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(UserMapper.class);
beanDefinition.setBeanClass(LubanFactoryBean.class);
//添加 beanDefinition
registry.registerBeanDefinition("luban", beanDefinition);
//这个时候容器中就加入了两个bean
&luban : lubanImportBeanDefinitionRegistrar
luban :代理对象
}
}
如何使用上面这个组件呢
在配置类上导入这个组件即可
@Import(LubanImportBeanDefinitionRegistrar.class)
public class AppConfig {
}
优化
添加扫描注解(用于指定扫描的路径,导入LubanImportBeanDefinitionRegistrar组件)
@Retention(RetentionPolicy.RUNTIME)
@Import(LubanImportBeanDefinitionRegistrar.class)
public @interface LubanScan {
}
LubanImportBeanDefinitionRegistrar获取动态生成BeanDefinition
在LubanImportBeanDefinitionRegistrar中,我们可以去扫描Mapper,在LubanImportBeanDefinitionRegistrar我们可以通过AnnotationMetadata获取到对应的@LubanScan注解,所以我们可以在@LubanScan上设置一个value,用来指定待扫描的包路径。然后在LubanImportBeanDefinitionRegistrar中获取所设置的包路径,然后扫描该路径下的所有Mapper,生成BeanDefinition,放入Spring容器中
