spring作为最为经典的架构之一最大的优势就是基于AOP设计和IOC容器,使得框架具有很好的可扩展性。
那当我们将另一个框架与spring结合时我需要怎么做呢?这时候就需要使用spring为我们提供的各种各样的钩子(hook)了。
ImportBeanDefinitionRegistrar
@Configuration
@Import(MyImportBeanDefinitionRegistrar.class)
public class MyConfig {
}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
System.out.println("MyIBDR的registerBeanDefinitions");
}
}
这个实现了接口后当被@Import的时候会被触发,registerBeanDefinitions方法中包含了两个参数,importingClassMetadata里存放了被标识的Bean的信息(这里是MyConfig),registry中存放的是BeanDefinition的注册器;
这里要解释一下BeanDefinition是什么,BeanDefinition是框架通过xml或者annotation获得的class信息这时还不是我们使用的bean,BeanDefinition.get()后才是真正的可使用的实体bean。
这个BeanDefinition是可以修改的,因此我们使用用的mybatis框架就是通过这个方法将自己的没有实现类的接口注入到了spring的容器中,大概的实现方式是这样的:
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(MyInterface.class).getBeanDefinition();
beanDefinition.setBeanClass(MyFactory.class);
registry.registerBeanDefinition("com.example.demo.MyInterface",beanDefinition);
}
public interface MyInterface {
String test(String param1,Integer param2);
List<String> testa(String param);
}
public class MyFactory implements FactoryBean {
@Override
public Object getObject() throws Exception {
return (MyInterface)Proxy.newProxyInstance(MyInterface.class.getClassLoader(), new Class[] { MyInterface.class }, new MyProxy());
}
@Override
public Class<?> getObjectType() {
return MyInterface.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
public class MyProxy implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
if("testa".equals(name)){
return new ArrayList<>();
}else {
return "三生三世";
}
}
}
这里我们可以看到MyInterface没有实现类,他是设置了一个FactoryBean并在getObject方法中声明了一个动态代理类(MyProxy)来处理,我们创建了一个BeanDefinition并设置了他的FactoryBean,在FactoryBean中声明了一个代理类。
总结
spring在生成Bean放入IOC容器之前是可以设置BeanDefinition的FactoryBean,通过不同的FactoryBean来实现不同的功能
感慨
在我刚刚接触mybatis的时候那个阶段只是会使用,惊叹于mybatis的简洁灵活的语言却从来没想过怎么实现的;直到有一天想将一些代码封装的更加优雅更加完美,参考了一下mybatis-spring的源码后才知道了spring的灵活可扩展性,以前总是说spring的反射IOC容器一直以为只是一个map里边存放了很多bean,这样就不需要我们每次使用的时候new一下了节省堆内存,其实spring框架真正厉害的地方是对bean的操控,它可以在你启动框架的时候做很多事,使得你的框架随着需求的变化而变化。
本文探讨了Spring框架如何通过AOP设计和IOC容器提供高度可扩展性,特别是在与其他框架结合时。通过ImportBeanDefinitionRegistrar接口,开发者可以自定义BeanDefinition,实现如MyBatis等框架的无缝集成。

796

被折叠的 条评论
为什么被折叠?



