BeanFactory动态注入到Interface

有时候代码需要灵活的返回需要的一些对象,这时候我们往往用接口去承载返回的对象。尤其像spring这种框架,可以用@Resource的name属性进行区别。但是这种需要开发者在注入ioc中就提前申明name属性,在针对多个实现的情况下。作者今天看到另外一种姿势,主要是通过BeanFactory接口以及ApplicationContextInitializer、BeanDefinitionRegistryPostProcessor等接口去实现的。通过这些接口我们可以做更多的扩展,从而避免写name去标记的问题,其次更深化我们对spring的应用吧。

1、首先定义承载对象的接口

public interface Bean {
}

2、定义BeanFactory,实现getObject方法。

public class MyBeanFactoryimplements FactoryBean{




    private String name;




    private String age;




    public String getName() {
        return name;
    }




    public void setName(String name) {
        this.name = name;
    }




    public String getAge() {
        return age;
    }




    public void setAge(String age) {
        this.age = age;
    }




    public static final Mapmap=new HashMap<>();




    @Override
    public T getObject() throws Exception {
        if (CollectionUtils.isEmpty(map)||!map.containsKey("lele")){
            synchronized (map){
                return (T) execute();
            }
        }else{
            return (T) map.get("lele");
        }
    }




    private Object execute() {
        Mybean mybean = new Mybean(name,age);
        map.put("lele",mybean);
        return mybean;
    }




    @Override
    public Class getObjectType() {
        return null;
    }




    @Override
    public boolean isSingleton() {
        return FactoryBean.super.isSingleton();
    }
}

3、将BeanFactory注入到ioc容器。

public class MyBeanFactoryBean extends MyBeanFactory{


}

Spring注入bean装配厂工具类

public class MySpringContentUtils {




    public static ConfigurableApplicationContext context;




    public static ConfigurableApplicationContext getContext() {
        return context;
    }




    public static void setContext(ConfigurableApplicationContext context) {
        MySpringContentUtils.context = context;
    }




    public static void registerBean(String name, Class factoryClazz, Class beanClazz, MutablePropertyValues mpv) throws BeanDefinitionStoreException {
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(beanClazz);
        GenericBeanDefinition beanDefinition = (GenericBeanDefinition)beanDefinitionBuilder.getRawBeanDefinition();
        beanDefinition.setBeanClass(factoryClazz == null ? beanClazz : factoryClazz);
        beanDefinition.setPropertyValues(mpv);
        BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry)context.getBeanFactory();
        beanFactory.registerBeanDefinition(name, beanDefinition);
    }




    public staticT getBean(String name) throws BeansException {
        return (T) context.getBean(name);
    }
}

将MyBeanFactory注入到beanDefianition中

@Configuration
public class MyConfig implements BeanDefinitionRegistryPostProcessor {


    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        MutablePropertyValues mv=new MutablePropertyValues();
        mv.add("name","jasldf");
        mv.add("age","123");
        MySpringContentUtils.registerBean("jk",MyBeanFactoryBean.class,Mybean.class,mv);
    }


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    }
}

上述中我们要想将MyBeanFactoryBean注入到IOC中,首先我们需要让MySpringContentUtils 拿到ioc,并用静态变量去引用其地址。这时候我们可以采用ApplicationContextInitializer的能力。

public class MyTianApplicationInitlize implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        MySpringContentUtils.setContext(configurableApplicationContext);
    }
}

写完代码,我们在resources目录下创建META-INF文件夹,并创建spring.fatories文件,并填入我们的初始化类的路径。具体如图所示。

ebbb47d76ef133fcfc3c89e45f60e103.png

至此,我们需要的功能就已经写完了。这里我们测试一下。

ca0ff6c70a99bc90d924c1b4146af6c9.png

测试如下;

fd1495dff4c94f1b178572796fa4a721.png

当然实现上述功能,其实还有其他的方法,这块将spring的多个接口算是整合起来学习一下,换句话说就是写个笔记,用的时候好查一些。

a63bdc797480d0e6fe8334d4cfd6f9a2.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值