spring作为一个开放式编程框架,它提供了很多拓展点,本章主要实现下MapperScan注解,
本篇文章实现的mapperScan是一个阉割版,没有实现扫描的功能,也没有真正去链接数据库,只是对mapperScan实现思路的一个体现
项目和简单,核心类是MyBatisImportBeanDefinitionRegistrar
public class MyBatisImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar, InvocationHandler, FactoryBean {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if(importingClassMetadata.hasAnnotation(EnabledMapper.class.getName())){
String[] beanNamesForAnnotation = ((DefaultListableBeanFactory) registry).getBeanNamesForAnnotation(Mapper.class);
for (String beanName : beanNamesForAnnotation) {
BeanDefinition bd = registry.getBeanDefinition(beanName);
String infClass = bd.getBeanClassName();
bd.setBeanClassName(MyBatisImportBeanDefinitionRegistrar.class.getName());
bd.getConstructorArgumentValues().addGenericArgumentValue(infClass);
registry.registerBeanDefinition(beanName,bd);
}
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 这里就不真正去真正的链接jdbc了
UserVO user = new UserVO();
user.setId((Long) args[0]);
user.setUserCode("Test");
user.setUserName("测试");
return user;
}
private String infClass;
public MyBatisImportBeanDefinitionRegistrar(){}
public MyBatisImportBeanDefinitionRegistrar(String infClass){
this.infClass = infClass;
}
@Override
public Object getObject() throws Exception {
return Proxy.newProxyInstance(this.getClass().getClassLoader(),new Class[]{Class.forName(infClass)},this);
}
@Override
public Class<?> getObjectType() {
try {
return Class.forName(infClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
结果执行
此次拓展是通过ImportBeanDefinitionRegistrar,FactoryBean和InvocationHandler3个接口协作实现
通过jdk的动态代理创建对象,然后通过FactoryBean创建对象,再由spring管理,不直接将代理对象放到spring中的原因是因为,spring有自己的一套创建对象的过程,不能直接替代,只能通过手段干预。