BeanFactory动态注入到Interface

共 3673字,需浏览 8分钟

 ·

2022-04-10 20:02

有时候代码需要灵活的返回需要的一些对象,这时候我们往往用接口去承载返回的对象。尤其像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中

@Configurationpublic 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文件,并填入我们的初始化类的路径。具体如图所示。



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

测试如下;


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





浏览 15
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报