Spring中的那些钩子hook--ImportBeanDefinitionRegistrar

本文探讨了Spring框架如何通过AOP设计和IOC容器提供高度可扩展性,特别是在与其他框架结合时。通过ImportBeanDefinitionRegistrar接口,开发者可以自定义BeanDefinition,实现如MyBatis等框架的无缝集成。

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的操控,它可以在你启动框架的时候做很多事,使得你的框架随着需求的变化而变化。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值