本文是一個(gè) Spring 擴(kuò)展支持 SPEL 的簡(jiǎn)單模式,方便第三方通過(guò) Spring 提供額外功能。
簡(jiǎn)化版方式
這種方式可以在任何能獲取ApplicationContext
的地方使用。還可以提取一個(gè)方法處理動(dòng)態(tài) SPEL 表達(dá)式。
import org.springframework.aop.support.AopUtils;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.*;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.context.annotation.Bean;import org.springframework.context.expression.StandardBeanExpressionResolver;import org.springframework.core.annotation.AnnotationUtils;import java.lang.reflect.Method;/** * 針對(duì) Spring 實(shí)現(xiàn)某些特殊邏輯時(shí),支持 SPEL 表達(dá)式 * @author liuzh */public class SpelUtil implements ApplicationContextAware { /** * 通過(guò) ApplicationContext 處理時(shí) * @param applicationContext * @throws BeansException */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (applicationContext instanceof ConfigurableApplicationContext) { ConfigurableApplicationContext context = (ConfigurableApplicationContext)applicationContext; ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); StandardBeanExpressionResolver expressionResolver = new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()); for (String definitionName : applicationContext.getBeanDefinitionNames()) { BeanDefinition definition = beanFactory.getBeanDefinition(definitionName); Scope scope = (definition != null ? beanFactory.getRegisteredScope(definition.getScope()) : null); //根據(jù)自己邏輯處理 //例如獲取 bean Object bean = applicationContext.getBean(definitionName); //獲取實(shí)際類(lèi)型 Class<?> targetClass = AopUtils.getTargetClass(bean); //獲取所有方法 for (Method method : targetClass.getDeclaredMethods()) { //獲取自定義的注解(Bean是個(gè)例子) Bean annotation = AnnotationUtils.findAnnotation(method, Bean.class); //假設(shè)下面的 value 支持 SPEL for (String val : annotation.value()) { //解析 ${} 方式的值 val = beanFactory.resolveEmbeddedValue(val); //解析 SPEL 表達(dá)式 Object value = expressionResolver.evaluate(val, new BeanExpressionContext(beanFactory, scope)); //TODO 其他邏輯 } } } } }}
上面是完全針對(duì)ApplicationContext
的,下面是更推薦的一種用法。
推薦方式
import org.springframework.aop.support.AopUtils;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanClassLoaderAware;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.beans.factory.config.*;import org.springframework.context.annotation.Bean;import org.springframework.context.expression.StandardBeanExpressionResolver;import org.springframework.core.annotation.AnnotationUtils;import org.springframework.util.ReflectionUtils;/** * 針對(duì) Spring 實(shí)現(xiàn)某些特殊邏輯時(shí),支持 SPEL 表達(dá)式 * @author liuzh */public class SpelUtil2 implements BeanPostProcessor, BeanFactoryAware, BeanClassLoaderAware { private BeanFactory beanFactory; private BeanExpressionResolver resolver; private BeanExpressionContext expressionContext; /** * 解析 SPEL * @param value * @return */ private Object resolveExpression(String value){ String resolvedValue = resolve(value); if (!(resolvedValue.startsWith("#{") && value.endsWith("}"))) { return resolvedValue; } return this.resolver.evaluate(resolvedValue, this.expressionContext); } /** * 解析 ${} * @param value * @return */ private String resolve(String value){ if (this.beanFactory != null && this.beanFactory instanceof ConfigurableBeanFactory) { return ((ConfigurableBeanFactory) this.beanFactory).resolveEmbeddedValue(value); } return value; } @Override public void setBeanClassLoader(ClassLoader classLoader) { this.resolver = new StandardBeanExpressionResolver(classLoader); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; if(beanFactory instanceof ConfigurableListableBeanFactory){ this.resolver = ((ConfigurableListableBeanFactory) beanFactory).getBeanExpressionResolver(); this.expressionContext = new BeanExpressionContext((ConfigurableListableBeanFactory) beanFactory, null); } } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } /** * 對(duì) bean 的后置處理 * @param bean * @param beanName * @return * @throws BeansException */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { //獲取實(shí)際類(lèi)型 Class<?> targetClass = AopUtils.getTargetClass(bean); //獲取所有方法 ReflectionUtils.doWithMethods(targetClass, method -> { //獲取自定義的注解(Bean是個(gè)例子) Bean annotation = AnnotationUtils.findAnnotation(method, Bean.class); //假設(shè)下面的 value 支持 SPEL for (String val : annotation.value()) { //解析表達(dá)式 Object value = resolveExpression(val); //TODO 其他邏輯 } }, method -> { //TODO 過(guò)濾方法 return true; }); return null; }}
這種方式利用了 Spring 生命周期的幾個(gè)接口來(lái)獲取需要用到的對(duì)象。
Spring 生命周期調(diào)用順序
擴(kuò)展 Spring 我們必須了解這個(gè)順序,否則就沒(méi)法正確的使用各中對(duì)象。
完整的初始化方法及其標(biāo)準(zhǔn)順序是:
關(guān)閉bean工廠時(shí),以下生命周期方法適用:
參考:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/BeanFactory.html
靈活運(yùn)用
利用上述模式可以實(shí)現(xiàn)很多便捷的操作。
Spring 中,使用類(lèi)似模式的地方有:
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)VeVb武林網(wǎng)的支持。
新聞熱點(diǎn)
疑難解答
圖片精選