Spring原理篇(12)--架构整合流程;该篇章讲解Spring在整合架构的时候的思路;

# 我们的Mapper 是一个接口 此时 在我们Service 注入了这个接口; 并且进行sql执行; 在Mybatis中 它会使用代理 进行接口实现; 并且最终把该对象的实现类 注入到这里来; 我们现在这里并没做这个类的实现; 现在执行肯定是报错的; 我们该如何把这个接口变成Bean呢? 答:使用FactoryBean 进行对象的创建. 我们知道 Spring内部使用了Cglib代理 所以不能代理接口;

1:我们利用FactoryBean 间接的创建Bean:

========================================================================================

/**

  • auth :huf

*/

@Component

public class HufFatoryBean implements FactoryBean {

@Override

public Object getObject() throws Exception {

Object object = Proxy.newProxyInstance(HufFatoryBean.class.getClassLoader(), new Class[]{StudentMapper.class}, new InvocationHandler() {

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println(method.getName());

return null;

}

});

return object;

}

@Override

public Class<?> getObjectType() {

return StudentMapper.class;

}

}

这样我们就可以通过FactoryBean 再利用 JDK 代理; 把接口变成对象 并且注入到容器中;

在这里插入图片描述

为什么是null 因为我Factory返回出来就是Null;


我们继续扩展; 假设我们有多个Mapper 一个StudentMapper 一个 TeacherMapper … 多个Mapper.那怎么办?

===================================================================================================================================

答: 我们把FactoryBean 变成 BeanDefinition 就可以了; 以下是演进展示;

我们先把HufFatoryBean 写活; 通过构造方法传入即将要代理的类Class. 这样 我们就可以只用一个FactoryBean 进行全部Mapper的代理.

/**

  • auth :huf

*/

@Component

public class HufFatoryBean implements FactoryBean {

private Class clazz;

public HufFatoryBean(Class clazz) {

this.clazz = clazz;

}

@Override

public Object getObject() throws Exception {

Object object = Proxy.newProxyInstance(HufFatoryBean.class.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println(method.getName());

return null;

}

});

return object;

}

@Override

public Class<?> getObjectType() {

return clazz;

}

}

然后 我们注册BeanDefinition

第一种方式

=================================================================

/**

  • Application启动类;

  • auth : huf

*/

public class ApplictionMain {

public static void main(String[] args) {

AnnotationConfigApplicationContext ap = new AnnotationConfigApplicationContext();

ap.register(AppConfig.class);


创建一个beanDefinition

AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();

传入我们的FactoryBean

beanDefinition.setBeanClass(HufFatoryBean.class);

通过构造方法 把Student传入

beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(StudentMapper.class);

注册BeanDefinition 把创建好的 BeanDefinition 传入进去;

ap.registerBeanDefinition(“studentMapper”,beanDefinition);

-------------------------以下也是一样

AbstractBeanDefinition beanDefinition1 = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();

beanDefinition1.setBeanClass(HufFatoryBean.class);

beanDefinition1.getConstructorArgumentValues().addGenericArgumentValue(TeacherMapper.class);

ap.registerBeanDefinition(“teacherMapper”,beanDefinition1);

启动

ap.refresh();

StudentService studentService = (StudentService) ap.getBean(“studentService”);

studentService.test();

}

}

这里 同学们应该都理解了吧? 到这里 其实思路就已经出来了; 我们不可能以这种方式去加载BeanDefinition; 以下 我介绍2种加载BeanDefinition的方式; 其实以前说过 再之前的篇章里边; 这里我写一次;


第二种BeanDefinitionRegistryPostProcessor

==================================================================================================

/**

  • auth : huf

*/

public class HufBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

@Override

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

创建一个beanDefinition

AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();

传入我们的FactoryBean

beanDefinition.setBeanClass(HufFatoryBean.class);

通过构造方法 把Student传入

beanDefinition.getConstructorArgumentValues().addGenericArgumentValu
e(StudentMapper.class);

注册BeanDefinition 把创建好的 BeanDefinition 传入进去;

ap.registerBeanDefinition(“studentMapper”,beanDefinition);

-------------------------以下也是一样

AbstractBeanDefinition beanDefinition1 = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();

beanDefinition1.setBeanClass(HufFatoryBean.class);

beanDefinition1.getConstructorArgumentValues().addGenericArgumentValue(TeacherMapper.class);

ap.registerBeanDefinition(“teacherMapper”,beanDefinition1);

}

@Override

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

}

}

这样是否是合理很多? 我们场景再继续往下深入一下; 如果我们之后想加一个Mapper 我们还得再这里写多一个BeanDefinition 是不是又突然觉得不太合理了?

===============================================================================================================================================

答: 我们可以利用 Scan 扫描的方式 进行Mapper扫描. 凡是再某个包下面的所有接口 我都认为它是Mapper 是否OK? 我们定义一个注解;

在这里插入图片描述

在这里插入图片描述

现在我们注入了扫描 我们会发现 之前用的BeanDefinitionRegistryPostProcessor 无法拿到我们的配置;我们就引出了另外一个

第三种ImportBeanDefinitionRegistrar

============================================================================================

在这里插入图片描述

这样 我们在配置文件中 可以通过@Inport(HufImportBeanDefinitionRegistrar.class) Spring捕捉到配置文件中的Import后 就可以调度这个方法 把BeanDefinition 加入容器中去; 这样我们继续改造我们的HufImportBeanDefinitionRegistrar 让他通过扫描的方式得到所有MapperClass 然后通过工厂的方式 生产BeanDefinition 注册到容器中; 以下是改造后的代码:

/**

  • auth : huf

*/

public class HufImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

@Override

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(HufMapperScan.class.getName());

String path = MapUtils.getString(annotationAttributes,“value”);

//Spring 原生扫描的方式 因为我们使用的是接口 所以我们必须继承这个类 并且进行改造

// ClassPathBeanDefinitionScanner scan = new ClassPathBeanDefinitionScanner(registry);

// scan.scan(path);

创建自己的MapperBeanDefinitionScanner

HufMapperBeanDefinitionScanner scanner = new HufMapperBeanDefinitionScanner(registry);

该步骤是为了在扫描其中 如果有@Component 才会加入到容器 默认false 我改成true 就是 不管有没有 都是Bean

scanner.addIncludeFilter(new TypeFilter() {

@Override

public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {

return true;

}

});

scanner.scan(path);

}

}

HufMapperBeanDefinitionScanner

==========================================================================================

中间的doScan方法重写 是为了什么? 我们通过path路径扫描到的 是Mapper本身 并不是Factory 现在我们变成Factory 所以要从写Scan 方法 这时候 我们得到的BeanDefinition 就是我们想要的了; 这样我们的扫描组件就写完了

在这里插入图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值