Spring组件开发模式支持SPEL表达式
本文是一个Spring扩展支持SPEL的简单模式,方便第三方通过Spring提供额外功能。
简化版方式
这种方式可以在任何能获取ApplicationContext的地方使用。还可以提取一个方法处理动态SPEL表达式。
importorg.springframework.aop.support.AopUtils;
importorg.springframework.beans.BeansException;
importorg.springframework.beans.factory.config.*;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.ApplicationContextAware;
importorg.springframework.context.ConfigurableApplicationContext;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.expression.StandardBeanExpressionResolver;
importorg.springframework.core.annotation.AnnotationUtils;
importjava.lang.reflect.Method;
/**
*针对Spring实现某些特殊逻辑时,支持SPEL表达式
*@authorliuzh
*/
publicclassSpelUtilimplementsApplicationContextAware{
/**
*通过ApplicationContext处理时
*@paramapplicationContext
*@throwsBeansException
*/
@Override
publicvoidsetApplicationContext(ApplicationContextapplicationContext)throwsBeansException{
if(applicationContextinstanceofConfigurableApplicationContext){
ConfigurableApplicationContextcontext=(ConfigurableApplicationContext)applicationContext;
ConfigurableListableBeanFactorybeanFactory=context.getBeanFactory();
StandardBeanExpressionResolverexpressionResolver=newStandardBeanExpressionResolver(beanFactory.getBeanClassLoader());
for(StringdefinitionName:applicationContext.getBeanDefinitionNames()){
BeanDefinitiondefinition=beanFactory.getBeanDefinition(definitionName);
Scopescope=(definition!=null?beanFactory.getRegisteredScope(definition.getScope()):null);
//根据自己逻辑处理
//例如获取bean
Objectbean=applicationContext.getBean(definitionName);
//获取实际类型
Class>targetClass=AopUtils.getTargetClass(bean);
//获取所有方法
for(Methodmethod:targetClass.getDeclaredMethods()){
//获取自定义的注解(Bean是个例子)
Beanannotation=AnnotationUtils.findAnnotation(method,Bean.class);
//假设下面的value支持SPEL
for(Stringval:annotation.value()){
//解析${}方式的值
val=beanFactory.resolveEmbeddedValue(val);
//解析SPEL表达式
Objectvalue=expressionResolver.evaluate(val,newBeanExpressionContext(beanFactory,scope));
//TODO其他逻辑
}
}
}
}
}
}
上面是完全针对ApplicationContext的,下面是更推荐的一种用法。
推荐方式
importorg.springframework.aop.support.AopUtils;
importorg.springframework.beans.BeansException;
importorg.springframework.beans.factory.BeanClassLoaderAware;
importorg.springframework.beans.factory.BeanFactory;
importorg.springframework.beans.factory.BeanFactoryAware;
importorg.springframework.beans.factory.config.*;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.expression.StandardBeanExpressionResolver;
importorg.springframework.core.annotation.AnnotationUtils;
importorg.springframework.util.ReflectionUtils;
/**
*针对Spring实现某些特殊逻辑时,支持SPEL表达式
*@authorliuzh
*/
publicclassSpelUtil2implementsBeanPostProcessor,BeanFactoryAware,BeanClassLoaderAware{
privateBeanFactorybeanFactory;
privateBeanExpressionResolverresolver;
privateBeanExpressionContextexpressionContext;
/**
*解析SPEL
*@paramvalue
*@return
*/
privateObjectresolveExpression(Stringvalue){
StringresolvedValue=resolve(value);
if(!(resolvedValue.startsWith("#{")&&value.endsWith("}"))){
returnresolvedValue;
}
returnthis.resolver.evaluate(resolvedValue,this.expressionContext);
}
/**
*解析${}
*@paramvalue
*@return
*/
privateStringresolve(Stringvalue){
if(this.beanFactory!=null&&this.beanFactoryinstanceofConfigurableBeanFactory){
return((ConfigurableBeanFactory)this.beanFactory).resolveEmbeddedValue(value);
}
returnvalue;
}
@Override
publicvoidsetBeanClassLoader(ClassLoaderclassLoader){
this.resolver=newStandardBeanExpressionResolver(classLoader);
}
@Override
publicvoidsetBeanFactory(BeanFactorybeanFactory)throwsBeansException{
this.beanFactory=beanFactory;
if(beanFactoryinstanceofConfigurableListableBeanFactory){
this.resolver=((ConfigurableListableBeanFactory)beanFactory).getBeanExpressionResolver();
this.expressionContext=newBeanExpressionContext((ConfigurableListableBeanFactory)beanFactory,null);
}
}
@Override
publicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{
returnbean;
}
/**
*对bean的后置处理
*@parambean
*@parambeanName
*@return
*@throwsBeansException
*/
@Override
publicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{
//获取实际类型
Class>targetClass=AopUtils.getTargetClass(bean);
//获取所有方法
ReflectionUtils.doWithMethods(targetClass,method->{
//获取自定义的注解(Bean是个例子)
Beanannotation=AnnotationUtils.findAnnotation(method,Bean.class);
//假设下面的value支持SPEL
for(Stringval:annotation.value()){
//解析表达式
Objectvalue=resolveExpression(val);
//TODO其他逻辑
}
},method->{
//TODO过滤方法
returntrue;
});
returnnull;
}
}
这种方式利用了Spring生命周期的几个接口来获取需要用到的对象。
Spring生命周期调用顺序
扩展Spring我们必须了解这个顺序,否则就没法正确的使用各中对象。
完整的初始化方法及其标准顺序是:
- BeanNameAware的setBeanName方法
- BeanClassLoaderAware的setBeanClassLoader方法
- BeanFactoryAware的setBeanFactory方法
- EnvironmentAware的setEnvironment方法
- EmbeddedValueResolverAware的setEmbeddedValueResolver方法
- ResourceLoaderAware的setResourceLoader方法(仅在应用程序上下文中运行时适用)
- ApplicationEventPublisherAware的setApplicationEventPublisher方法(仅在应用程序上下文中运行时适用)
- MessageSourceAware的setMessageSource方法(仅在应用程序上下文中运行时适用)
- ApplicationContextAware的setApplicationContext方法(仅在应用程序上下文中运行时适用)
- ServletContextAware的setServletContext方法(仅在Web应用程序上下文中运行时适用)
- BeanPostProcessors的postProcessBeforeInitialization方法
- InitializingBean的afterPropertiesSet方法
- 自定义初始化方法
- BeanPostProcessors的postProcessAfterInitialization方法
关闭bean工厂时,以下生命周期方法适用:
- DestructionAwareBeanPostProcessors的postProcessBeforeDestruction方法
- DisposableBean的destroy方法
- 自定义销毁方法
参考:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/BeanFactory.html
灵活运用
利用上述模式可以实现很多便捷的操作。
Spring中,使用类似模式的地方有:
- @Value注解支持SPEL(和${})
- @Cache相关的注解(支持SPEL)
- @EventListener注解
- @RabbitListener注解
- …
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对毛票票的支持。如果你想了解更多相关内容请查看下面相关链接