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注解
- …
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对毛票票的支持。如果你想了解更多相关内容请查看下面相关链接