中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用Spring擴展點

發布時間:2021-10-14 11:45:21 來源:億速云 閱讀:163 作者:iii 欄目:開發技術

這篇文章主要講解了“如何使用Spring擴展點”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何使用Spring擴展點”吧!

Spring常見擴展點

「BeanFactoryPostProcessor#postProcessBeanFactory」

有時候整個項目工程中bean的數量有上百個,而大部分單測依賴都是整個工程的xml,導致單測執行時需要很長時間(大部分時間耗費在xml中數百個單例非懶加載的bean的實例化及初始化過程)

解決方法:利用Spring提供的擴展點將xml中的bean設置為懶加載模式,省去了Bean的實例化與初始化時間

public class LazyBeanFactoryProcessor implements BeanFactoryPostProcessor {     @Override     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {         DefaultListableBeanFactory fac = (DefaultListableBeanFactory) beanFactory;         Map<String, AbstractBeanDefinition> map = (Map<String, AbstractBeanDefinition>) ReflectionTestUtils.getField(fac, "beanDefinitionMap");         for (Map.Entry<String, AbstractBeanDefinition> entry : map.entrySet()) {             //設置為懶加載             entry.getValue().setLazyInit(true);         }     } }

「InstantiationAwareBeanPostProcessor#postProcessPropertyValues」

非常規的配置項比如

<context:component-scan base-package="com.zhou" />

Spring提供了與之對應的特殊解析器

正是通過這些特殊的解析器才使得對應的配置項能夠生效

而針對這個特殊配置的解析器為 ComponentScanBeanDefinitionParser

在這個解析器的解析方法中,注冊了很多特殊的Bean

public BeanDefinition parse(Element element, ParserContext parserContext) {   //...   registerComponents(parserContext.getReaderContext(), beanDefinitions, element);     //...   return null; }
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(    BeanDefinitionRegistry registry, Object source) {    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);   //...     //@Autowire   if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {    RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);    def.setSource(source);    beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));   }    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.    //@Resource   if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {       //特殊的Bean    RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);    def.setSource(source);    beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));   }   //...   return beanDefs;  }

以@Resource為例,看看這個特殊的bean做了什么

public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor   implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {             public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds,        Object bean, String beanName) throws BeansException {           InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass());           try {             //屬性注入             metadata.inject(bean, beanName, pvs);           }           catch (Throwable ex) {             throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);           }           return pvs;     }      }

我們看到在postProcessPropertyValues方法中,進行了屬性注入

「invokeAware」

實現BeanFactoryAware接口的類,會由容器執行setBeanFactory方法將當前的容器BeanFactory注入到類中

@Bean class BeanFactoryHolder implements BeanFactoryAware{         private static BeanFactory beanFactory;          public void setBeanFactory(BeanFactory beanFactory) throws BeansException {         this.beanFactory = beanFactory;     } }

「BeanPostProcessor#postProcessBeforeInitialization」

實現ApplicationContextAware接口的類,會由容器執行setApplicationContext方法將當前的容器applicationContext注入到類中

@Bean class ApplicationContextAwareProcessor implements BeanPostProcessor {      private final ConfigurableApplicationContext applicationContext;      public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {       this.applicationContext = applicationContext;     }      @Override     public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {       //...       invokeAwareInterfaces(bean);       return bean;     }      private void invokeAwareInterfaces(Object bean) {         if (bean instanceof ApplicationContextAware) {           ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);         }     } }

我們看到是在BeanPostProcessor的postProcessBeforeInitialization中進行了setApplicationContext方法的調用

class ApplicationContextHolder implements ApplicationContextAware{         private static ApplicationContext applicationContext;          public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {         this.applicationContext = applicationContext;     } }

「afterPropertySet()和init-method」

目前很多Java中間件都是基本Spring  Framework搭建的,而這些中間件經常把入口放到afterPropertySet或者自定義的init中

「BeanPostProcessor#postProcessAfterInitialization」

熟悉aop的同學應該知道,aop底層是通過動態代理實現的

當配置了時候,默認開啟aop功能,相應地調用方需要被aop織入的對象也需要替換為動態代理對象

不知道大家有沒有思考過動態代理是如何「在調用方無感知情況下替換原始對象」的?

根據上文的講解,我們知道:

<aop:aspectj-autoproxy/>

Spring也提供了特殊的解析器,和其他的解析器類似,在核心的parse方法中注冊了特殊的bean

這里是一個BeanPostProcessor類型的bean

class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {  @Override  public BeanDefinition parse(Element element, ParserContext parserContext) {     //注冊特殊的bean   AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);   extendBeanDefinition(element, parserContext);   return null;     } }

將于當前bean對應的動態代理對象返回即可,該過程對調用方全部透明

public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {         if (bean != null) {           Object cacheKey = getCacheKey(bean.getClass(), beanName);           if (!this.earlyProxyReferences.containsKey(cacheKey)) {             //如果該類需要被代理,返回動態代理對象;反之,返回原對象             return wrapIfNecessary(bean, beanName, cacheKey);           }         }         return bean;  } }

正是利用Spring的這個擴展點實現了動態代理對象的替換

「destroy()和destroy-method」

bean生命周期的最后一個擴展點,該方法用于執行一些bean銷毀前的準備工作,比如將當前bean持有的一些資源釋放掉

感謝各位的閱讀,以上就是“如何使用Spring擴展點”的內容了,經過本文的學習后,相信大家對如何使用Spring擴展點這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

浦东新区| 蒙阴县| 常山县| 永新县| 汽车| 郧西县| 木兰县| 台南县| 南乐县| 南投县| 乡宁县| 祁阳县| 岐山县| 玉屏| 抚远县| 乐山市| 静海县| 淮北市| 灵川县| 涟源市| 富民县| 南川市| 孝昌县| 鲁山县| 安溪县| 浮山县| 昭通市| 五华县| 漳浦县| 那曲县| 金门县| 清水县| 威海市| 萨迦县| 洪泽县| 平罗县| 桐乡市| 公安县| 榆林市| 石泉县| 砚山县|