项目中要灵活使用static来标记一些常用得类,static得作用就是跨对象得存在性。只要类没有被卸载掉,那么static修饰得属性就一直在。因此我们可以用static来标记一些引用,因为static一直存在,那么我们通过static得修饰就可以获得其引用得地址,不论被应用得对象身处何方。 有了上述思想,我们就能想到在spring框架中,上下文是我们重点关切得对象。因此我们想着通过static来引用spring上下文,然后形成一个工具类。我们在项目得业务部分能够通过该工具类来操作我们得spring上下文。这块我们说一下spring扩展接口ApplicationContextInitializer,这个接口会在spring上下文刷新之前进行调用,相当于提前将容器进行对外得暴露,当然页提供了我们修改其属性得权力。ApplicationContextInitializer得执行在prepareContext中,这块之前也大概得说过了。
我们通过查看源码,发现这块传入得是ConfigurableApplicationContext,注意这块返回得是空,意思是我们可以对这里得context进行应用标记。
protected void applyInitializers(ConfigurableApplicationContext context) {
Iterator var2 = this.getInitializers().iterator();
while(var2.hasNext()) {
ApplicationContextInitializer initializer = (ApplicationContextInitializer)var2.next();
Class requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
通过以上得分析,我们就想这在initialize方法中将我们得上下文缓存进来。让我们来做个实践吧。
public class MyBean {
private String name;
private String config;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getConfig() {
return config;
}
public void setConfig(String config) {
this.config = config;
}
@Override
public String toString() {
return "MyBean{" +
"name='" + name + '\'' +
", config='" + config + '\'' +
'}';
}
}
静态Spring工具类
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);
}
}
自定义initlizer接口
public class MyTianApplicationInitlize implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
System.out.println("我来了...宝");
MySpringContentUtils.setContext(configurableApplicationContext);
}
}
测试类
public static void main(String[] args) throws InterruptedException {
SpringApplication builder=new SpringApplicationBuilder(Demo1Application.class).initializers(new MyTianApplicationInitlize()).build();
builder.run( args);
System.out.println(env.toString());
MutablePropertyValues mpv = new MutablePropertyValues();
mpv.addPropertyValue("name","tianjingle_initlizer");
MySpringContentUtils.registerBean("lisi",null, MyBean.class,mpv);
MyBean myBean= (MyBean) MySpringContentUtils.getContext().getBean("lisi");
System.out.println(myBean.toString());
}
效果
通过上述实践,我们实现了我们得目标。当然我们也可以采用spring.factories文件得方式进行添加initlizer工具。这种方式在springBoot中得starter中用得比较多,看这里。
响应得修改我们得启动类
public static void main(String[] args) throws InterruptedException {
// SpringApplication builder=new SpringApplicationBuilder(Demo1Application.class).initializers(new MyTianApplicationInitlize()).build();
// builder.run( args);
SpringApplication.run(Demo1Application.class,args);
System.out.println(env.toString());
MutablePropertyValues mpv = new MutablePropertyValues();
mpv.addPropertyValue("name","tianjingle_initlizer");
MySpringContentUtils.registerBean("lisi",null, MyBean.class,mpv);
MyBean myBean= (MyBean) MySpringContentUtils.getContext().getBean("lisi");
System.out.println(myBean.toString());
}
至于spring.factories文件得读取,这个在启动得时候springBoot就会加载。就说这么多吧。