明白我们需要的是什么

首先,当我们整合二者的时候,是不是一直都只有接口呢,而我们真正调用的是不是这个接口的一个代理类呢,所以我们目的其实就是把这个代理类作为bean给注入到spring容器中,这样我们就可以从容器中拿代理对象,并执行相应的操作。

FactoryBean生成bean(代理对象)

首先我们要知道FactoryBean是一个接口,实现它需要具体实现两个方法,getObject(),getObjectType(),当我们实现它的时候spring启动的时候就会判断有没有实现FactoryBean实现了的话就会调用getObject()方法。那我们就可以在这里做文章,返回一个代理对象(这里其实我们注入一个sqlsessionFactory就可以了,这样返回的就是mybaties的代理对象)给他。先看代码:

  1. @Component
  2. public class LubanFactoryBean implements FactoryBean {
  3. //这个表示传进来的接口的类型
  4. private Class mapperInterface;
  5. //通过构造器
  6. public LubanFactoryBean(Class mapperInterface) {
  7. this.mapperInterface = mapperInterface;
  8. }
  9. @Override
  10. public Object getObject() throws Exception {
  11. //这里就使用动态代理
  12. Object proxyInstance = Proxy.newProxyInstance(LubanFactoryBean.class.getClassLoader(),
  13. //×××××××注意看这里,我这里用的是属性,所以这个自定义FacotoryBean
  14. //就变的灵活了
  15. new Class[]{mapperInterface.class}, new
  16. InvocationHandler() {
  17. @Override
  18. public Object invoke(Object proxy, Method method, Obj
  19. ect[] args) throws Throwable {
  20. if (Object.class.equals(method.getDeclaringClass(
  21. ))) {
  22. return method.invoke(this, args);
  23. } else {
  24. //执行代理逻辑
  25. return null;
  26. }
  27. }
  28. });
  29. return proxyInstance;
  30. }
  31. @Override
  32. public Class<?> getObjectType() {
  33. return UserMapper.class;
  34. }
  35. }

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容器中