国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - 編程技術(shù) - 《Spring 手?jǐn)]專欄》:通過注解給屬性注入配置和Bean對(duì)象

《Spring 手?jǐn)]專欄》:通過注解給屬性注入配置和Bean對(duì)象

2021-08-04 23:07bugstack蟲洞棧小傅哥 編程技術(shù)

目前 IOC、AOP 兩大核心功能模塊的支撐下,完全可以管理 Bean 對(duì)象的注冊(cè)和獲取,不過這樣的使用方式總感覺像是刀耕火種有點(diǎn)難用。

《Spring 手?jǐn)]專欄》:通過注解給屬性注入配置和Bean對(duì)象

一、前言

 

寫代碼,就是從能用到好用的不斷折騰!

你聽過擾動(dòng)函數(shù)嗎?你寫過斐波那契(Fibonacci)散列嗎?你實(shí)現(xiàn)過梅森旋轉(zhuǎn)算法嗎?怎么 沒聽過這些寫不了代碼嗎!不會(huì)的,即使沒聽過你一樣可以寫的了代碼,比如你實(shí)現(xiàn)的數(shù)據(jù)庫路由數(shù)據(jù)總是落在1庫1表它不散列分布、你實(shí)現(xiàn)的抽獎(jiǎng)系統(tǒng)總是把運(yùn)營配置的最大紅包發(fā)出去提高了運(yùn)營成本、你開發(fā)的秒殺系統(tǒng)總是在開始后的1秒就掛了貨品根本給不出去。

除了一部分僅把編碼當(dāng)成搬磚應(yīng)付工作外的程序員,還有一部分總是在追求極致的碼農(nóng)。寫代碼還能賺錢,真開心! 這樣的碼農(nóng)總是會(huì)考慮??還有沒有更好的實(shí)現(xiàn)邏輯能讓代碼不僅是能用,還要好用呢?其實(shí)這一點(diǎn)的追求到完成,需要大量擴(kuò)展性學(xué)習(xí)和深度挖掘,這樣你設(shè)計(jì)出來的系統(tǒng)才更你考慮的更加全面,也能應(yīng)對(duì)各種復(fù)雜的場(chǎng)景。

二、目標(biāo)

 

在目前 IOC、AOP 兩大核心功能模塊的支撐下,完全可以管理 Bean 對(duì)象的注冊(cè)和獲取,不過這樣的使用方式總感覺像是刀耕火種有點(diǎn)難用。因此在上一章節(jié)我們解決需要手動(dòng)配置 Bean 對(duì)象到 spring.xml 文件中,改為可以自動(dòng)掃描帶有注解 @Component 的對(duì)象完成自動(dòng)裝配和注冊(cè)到 Spring 容器的操作。

那么在自動(dòng)掃描包注冊(cè) Bean 對(duì)象之后,就需要把原來在配置文件中通過 property name="token" 配置屬性和Bean的操作,也改為可以自動(dòng)注入。這就像我們使用 Spring 框架中 @Autowired、@Value 注解一樣,完成我們對(duì)屬性和對(duì)象的注入操作。

三、方案

 

其實(shí)從我們?cè)谕瓿?Bean 對(duì)象的基礎(chǔ)功能后,后續(xù)陸續(xù)添加的功能都是圍繞著 Bean 的生命周期進(jìn)行的,比如修改 Bean 的定義 BeanFactoryPostProcessor,處理 Bean 的屬性要用到 BeanPostProcessor,完成個(gè)性的屬性操作則專門繼承 BeanPostProcessor 提供新的接口,因?yàn)檫@樣才能通過 instanceof 判斷出具有標(biāo)記性的接口。所以關(guān)于 Bean 等等的操作,以及監(jiān)聽 Aware、獲取 BeanFactory,都需要在 Bean 的生命周期中完成。那么我們?cè)谠O(shè)計(jì)屬性和 Bean 對(duì)象的注入時(shí)候,也會(huì)用到 BeanPostProcessor 來完成在設(shè)置 Bean 屬性之前,允許 BeanPostProcessor 修改屬性值。整體設(shè)計(jì)結(jié)構(gòu)如下圖:

《Spring 手?jǐn)]專欄》:通過注解給屬性注入配置和Bean對(duì)象

  • 要處理自動(dòng)掃描注入,包括屬性注入、對(duì)象注入,則需要在對(duì)象屬性 applyPropertyValues 填充之前 ,把屬性信息寫入到 PropertyValues 的集合中去。這一步的操作相當(dāng)于是解決了以前在 spring.xml 配置屬性的過程。
  • 而在屬性的讀取中,需要依賴于對(duì) Bean 對(duì)象的類中屬性的配置了注解的掃描,field.getAnnotation(Value.class); 依次拿出符合的屬性并填充上相應(yīng)的配置信息。這里有一點(diǎn) ,屬性的配置信息需要依賴于 BeanFactoryPostProcessor 的實(shí)現(xiàn)類 PropertyPlaceholderConfigurer,把值寫入到 AbstractBeanFactory的embeddedValueResolvers集合中,這樣才能在屬性填充中利用 beanFactory 獲取相應(yīng)的屬性值
  • 還有一個(gè)是關(guān)于 @Autowired 對(duì)于對(duì)象的注入,其實(shí)這一個(gè)和屬性注入的唯一區(qū)別是對(duì)于對(duì)象的獲取 beanFactory.getBean(fieldType),其他就沒有什么差一點(diǎn)了。
  • 當(dāng)所有的屬性被設(shè)置到 PropertyValues 完成以后,接下來就到了創(chuàng)建對(duì)象的下一步,屬性填充,而此時(shí)就會(huì)把我們一一獲取到的配置和對(duì)象填充到屬性上,也就實(shí)現(xiàn)了自動(dòng)注入的功能。

四、實(shí)現(xiàn)

 

1. 工程結(jié)構(gòu)

  1. small-spring-step-14 
  2. └── src 
  3.     ├── main 
  4.     │   └── java 
  5.     │       └── cn.bugstack.springframework 
  6.     │           ├── aop 
  7.     │           │   ├── aspectj 
  8.     │           │   │   └── AspectJExpressionPointcut.java 
  9.     │           │   │   └── AspectJExpressionPointcutAdvisor.java 
  10.     │           │   ├── framework  
  11.     │           │   │   ├── adapter 
  12.     │           │   │   │   └── MethodBeforeAdviceInterceptor.java 
  13.     │           │   │   ├── autoproxy 
  14.     │           │   │   │   └── MethodBeforeAdviceInterceptor.java 
  15.     │           │   │   ├── AopProxy.java 
  16.     │           │   │   ├── Cglib2AopProxy.java 
  17.     │           │   │   ├── JdkDynamicAopProxy.java 
  18.     │           │   │   ├── ProxyFactory.java 
  19.     │           │   │   └── ReflectiveMethodInvocation.java 
  20.     │           │   ├── AdvisedSupport.java 
  21.     │           │   ├── Advisor.java 
  22.     │           │   ├── BeforeAdvice.java 
  23.     │           │   ├── ClassFilter.java 
  24.     │           │   ├── MethodBeforeAdvice.java 
  25.     │           │   ├── MethodMatcher.java 
  26.     │           │   ├── Pointcut.java 
  27.     │           │   ├── PointcutAdvisor.java 
  28.     │           │   └── TargetSource.java 
  29.     │           ├── beans 
  30.     │           │   ├── factory   
  31.     │           │   │   ├── annotation 
  32.     │           │   │   │   ├── Autowired.java 
  33.     │           │   │   │   ├── AutowiredAnnotationBeanPostProcessor.java 
  34.     │           │   │   │   ├── Qualifier.java 
  35.     │           │   │   │   └── Value.java 
  36.     │           │   │   ├── config 
  37.     │           │   │   │   ├── AutowireCapableBeanFactory.java 
  38.     │           │   │   │   ├── BeanDefinition.java 
  39.     │           │   │   │   ├── BeanFactoryPostProcessor.java 
  40.     │           │   │   │   ├── BeanPostProcessor.java 
  41.     │           │   │   │   ├── BeanReference.java 
  42.     │           │   │   │   ├── ConfigurableBeanFactory.java 
  43.     │           │   │   │   ├── InstantiationAwareBeanPostProcessor.java 
  44.     │           │   │   │   └── SingletonBeanRegistry.java 
  45.     │           │   │   ├── support 
  46.     │           │   │   │   ├── AbstractAutowireCapableBeanFactory.java 
  47.     │           │   │   │   ├── AbstractBeanDefinitionReader.java 
  48.     │           │   │   │   ├── AbstractBeanFactory.java 
  49.     │           │   │   │   ├── BeanDefinitionReader.java 
  50.     │           │   │   │   ├── BeanDefinitionRegistry.java 
  51.     │           │   │   │   ├── CglibSubclassingInstantiationStrategy.java 
  52.     │           │   │   │   ├── DefaultListableBeanFactory.java 
  53.     │           │   │   │   ├── DefaultSingletonBeanRegistry.java 
  54.     │           │   │   │   ├── DisposableBeanAdapter.java 
  55.     │           │   │   │   ├── FactoryBeanRegistrySupport.java 
  56.     │           │   │   │   ├── InstantiationStrategy.java 
  57.     │           │   │   │   └── SimpleInstantiationStrategy.java   
  58.     │           │   │   ├── support 
  59.     │           │   │   │   └── XmlBeanDefinitionReader.java 
  60.     │           │   │   ├── Aware.java 
  61.     │           │   │   ├── BeanClassLoaderAware.java 
  62.     │           │   │   ├── BeanFactory.java 
  63.     │           │   │   ├── BeanFactoryAware.java 
  64.     │           │   │   ├── BeanNameAware.java 
  65.     │           │   │   ├── ConfigurableListableBeanFactory.java 
  66.     │           │   │   ├── DisposableBean.java 
  67.     │           │   │   ├── FactoryBean.java 
  68.     │           │   │   ├── HierarchicalBeanFactory.java 
  69.     │           │   │   ├── InitializingBean.java 
  70.     │           │   │   ├── ListableBeanFactory.java 
  71.     │           │   │   └── PropertyPlaceholderConfigurer.java 
  72.     │           │   ├── BeansException.java 
  73.     │           │   ├── PropertyValue.java 
  74.     │           │   └── PropertyValues.java  
  75.     │           ├── context 
  76.     │           │   ├── annotation 
  77.     │           │   │   ├── ClassPathBeanDefinitionScanner.java  
  78.     │           │   │   ├── ClassPathScanningCandidateComponentProvider.java  
  79.     │           │   │   └── Scope.java  
  80.     │           │   ├── event 
  81.     │           │   │   ├── AbstractApplicationEventMulticaster.java  
  82.     │           │   │   ├── ApplicationContextEvent.java  
  83.     │           │   │   ├── ApplicationEventMulticaster.java  
  84.     │           │   │   ├── ContextClosedEvent.java  
  85.     │           │   │   ├── ContextRefreshedEvent.java  
  86.     │           │   │   └── SimpleApplicationEventMulticaster.java  
  87.     │           │   ├── support 
  88.     │           │   │   ├── AbstractApplicationContext.java  
  89.     │           │   │   ├── AbstractRefreshableApplicationContext.java  
  90.     │           │   │   ├── AbstractXmlApplicationContext.java  
  91.     │           │   │   ├── ApplicationContextAwareProcessor.java  
  92.     │           │   │   └── ClassPathXmlApplicationContext.java  
  93.     │           │   ├── ApplicationContext.java  
  94.     │           │   ├── ApplicationContextAware.java  
  95.     │           │   ├── ApplicationEvent.java  
  96.     │           │   ├── ApplicationEventPublisher.java  
  97.     │           │   ├── ApplicationListener.java  
  98.     │           │   └── ConfigurableApplicationContext.java 
  99.     │           ├── core.io 
  100.     │           │   ├── ClassPathResource.java  
  101.     │           │   ├── DefaultResourceLoader.java  
  102.     │           │   ├── FileSystemResource.java  
  103.     │           │   ├── Resource.java  
  104.     │           │   ├── ResourceLoader.java 
  105.     │           │   └── UrlResource.java 
  106.     │           ├── stereotype 
  107.     │           │   └── Component.java 
  108.     │           └── utils 
  109.     │               ├── ClassUtils.java 
  110.     │               └── StringValueResolver.java 
  111.     └── test 
  112.         └── java 
  113.             └── cn.bugstack.springframework.test 
  114.                 ├── bean 
  115.                 │   ├── IUserService.java 
  116.                 │   └── UserService.java 
  117.                 └── ApiTest.java 

自動(dòng)掃描注入占位符配置和對(duì)象的類關(guān)系,如圖 15-2

《Spring 手?jǐn)]專欄》:通過注解給屬性注入配置和Bean對(duì)象

圖 15-2

  • 在整個(gè)類圖中以圍繞實(shí)現(xiàn)接口 InstantiationAwareBeanPostProcessor 的類 AutowiredAnnotationBeanPostProcessor 作為入口點(diǎn),被 AbstractAutowireCapableBeanFactory創(chuàng)建 Bean 對(duì)象過程中調(diào)用掃描整個(gè)類的屬性配置中含有自定義注解 Value、Autowired、Qualifier,的屬性值。
  • 這里稍有變動(dòng)的是關(guān)于屬性值信息的獲取,在注解配置的屬性字段掃描到信息注入時(shí),包括了占位符從配置文件獲取信息也包括 Bean 對(duì)象,Bean 對(duì)象可以直接獲取,但配置信息需要在 AbstractBeanFactory 中添加新的屬性集合 embeddedValueResolvers,由 PropertyPlaceholderConfigurer#postProcessBeanFactory 進(jìn)行操作填充到屬性集合中。

2. 把讀取到屬性填充到容器

定義解析字符串接口

cn.bugstack.springframework.util.StringValueResolver

  1. public interface StringValueResolver { 
  2.  
  3.     String resolveStringValue(String strVal); 
  4.  
  • 接口 StringValueResolver 是一個(gè)解析字符串操作的接口

填充字符串

  1. public class PropertyPlaceholderConfigurer implements BeanFactoryPostProcessor { 
  2.  
  3.     @Override 
  4.     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 
  5.         try { 
  6.             // 加載屬性文件 
  7.             DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); 
  8.             Resource resource = resourceLoader.getResource(location); 
  9.              
  10.             // ... 占位符替換屬性值、設(shè)置屬性值 
  11.  
  12.             // 向容器中添加字符串解析器,供解析@Value注解使用 
  13.             StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(properties); 
  14.             beanFactory.addEmbeddedValueResolver(valueResolver); 
  15.              
  16.         } catch (IOException e) { 
  17.             throw new BeansException("Could not load properties", e); 
  18.         } 
  19.     } 
  20.  
  21.     private class PlaceholderResolvingStringValueResolver implements StringValueResolver { 
  22.  
  23.         private final Properties properties; 
  24.  
  25.         public PlaceholderResolvingStringValueResolver(Properties properties) { 
  26.             this.properties = properties; 
  27.         } 
  28.  
  29.         @Override 
  30.         public String resolveStringValue(String strVal) { 
  31.             return PropertyPlaceholderConfigurer.this.resolvePlaceholder(strVal, properties); 
  32.         } 
  33.  
  34.     } 
  35.  
  • 在解析屬性配置的類 PropertyPlaceholderConfigurer 中,最主要的其實(shí)就是這行代碼的操作 beanFactory.addEmbeddedValueResolver(valueResolver) 這是把屬性值寫入到了 AbstractBeanFactory 的 embeddedValueResolvers 中。
  • 這里說明下,embeddedValueResolvers 是 AbstractBeanFactory 類新增加的集合 List embeddedValueResolvers String resolvers to apply e.g. to annotation attribute values

3. 自定義屬性注入注解

自定義注解,Autowired、Qualifier、Value

  1. @Retention(RetentionPolicy.RUNTIME) 
  2. @Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD}) 
  3. public @interface Autowired { 
  4.  
  5. @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) 
  6. @Retention(RetentionPolicy.RUNTIME) 
  7. @Inherited 
  8. @Documented 
  9. public @interface Qualifier { 
  10.  
  11.     String value() default ""
  12.  
  13. }   
  14.  
  15. @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) 
  16. @Retention(RetentionPolicy.RUNTIME) 
  17. @Documented 
  18. public @interface Value { 
  19.  
  20.     /** 
  21.      * The actual value expression: e.g. "#{systemProperties.myProp}"
  22.      */ 
  23.     String value(); 
  24.  

3個(gè)注解在我們?nèi)粘J褂?Spring 也是非常常見的,注入對(duì)象、注入屬性,而 Qualifier 一般與 Autowired 配合使用。

4. 掃描自定義注解

cn.bugstack.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor

  1. public class AutowiredAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware { 
  2.  
  3.     private ConfigurableListableBeanFactory beanFactory; 
  4.  
  5.     @Override 
  6.     public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 
  7.         this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; 
  8.     } 
  9.  
  10.     @Override 
  11.     public PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException { 
  12.         // 1. 處理注解 @Value 
  13.         Class<?> clazz = bean.getClass(); 
  14.         clazz = ClassUtils.isCglibProxyClass(clazz) ? clazz.getSuperclass() : clazz; 
  15.  
  16.         Field[] declaredFields = clazz.getDeclaredFields(); 
  17.  
  18.         for (Field field : declaredFields) { 
  19.             Value valueAnnotation = field.getAnnotation(Value.class); 
  20.             if (null != valueAnnotation) { 
  21.                 String value = valueAnnotation.value(); 
  22.                 value = beanFactory.resolveEmbeddedValue(value); 
  23.                 BeanUtil.setFieldValue(bean, field.getName(), value); 
  24.             } 
  25.         } 
  26.  
  27.         // 2. 處理注解 @Autowired 
  28.         for (Field field : declaredFields) { 
  29.             Autowired autowiredAnnotation = field.getAnnotation(Autowired.class); 
  30.             if (null != autowiredAnnotation) { 
  31.                 Class<?> fieldType = field.getType(); 
  32.                 String dependentBeanName = null
  33.                 Qualifier qualifierAnnotation = field.getAnnotation(Qualifier.class); 
  34.                 Object dependentBean = null
  35.                 if (null != qualifierAnnotation) { 
  36.                     dependentBeanName = qualifierAnnotation.value(); 
  37.                     dependentBean = beanFactory.getBean(dependentBeanName, fieldType); 
  38.                 } else { 
  39.                     dependentBean = beanFactory.getBean(fieldType); 
  40.                 } 
  41.                 BeanUtil.setFieldValue(bean, field.getName(), dependentBean); 
  42.             } 
  43.         } 
  44.  
  45.         return pvs; 
  46.     } 
  47.  
  • AutowiredAnnotationBeanPostProcessor 是實(shí)現(xiàn)接口 InstantiationAwareBeanPostProcessor 的一個(gè)用于在 Bean 對(duì)象實(shí)例化完成后,設(shè)置屬性操作前的處理屬性信息的類和操作方法。只有實(shí)現(xiàn)了 BeanPostProcessor 接口才有機(jī)會(huì)在 Bean 的生命周期中處理初始化信息
  • 核心方法 postProcessPropertyValues,主要用于處理類含有 @Value、@Autowired 注解的屬性,進(jìn)行屬性信息的提取和設(shè)置。
  • 這里需要注意一點(diǎn)因?yàn)槲覀冊(cè)?AbstractAutowireCapableBeanFactory 類中使用的是 CglibSubclassingInstantiationStrategy 進(jìn)行類的創(chuàng)建,所以在 AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues 中需要判斷是否為 CGlib 創(chuàng)建對(duì)象,否則是不能正確拿到類信息的。ClassUtils.isCglibProxyClass(clazz) ? clazz.getSuperclass() : clazz;

5. 在Bean的生命周期中調(diào)用屬性注入

cn.bugstack.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

  1. public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { 
  2.  
  3.     private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy(); 
  4.  
  5.     @Override 
  6.     protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException { 
  7.         Object bean = null
  8.         try { 
  9.             // 判斷是否返回代理 Bean 對(duì)象 
  10.             bean = resolveBeforeInstantiation(beanName, beanDefinition); 
  11.             if (null != bean) { 
  12.                 return bean; 
  13.             } 
  14.             // 實(shí)例化 Bean 
  15.             bean = createBeanInstance(beanDefinition, beanName, args); 
  16.             // 在設(shè)置 Bean 屬性之前,允許 BeanPostProcessor 修改屬性值 
  17.             applyBeanPostProcessorsBeforeApplyingPropertyValues(beanName, bean, beanDefinition); 
  18.             // 給 Bean 填充屬性 
  19.             applyPropertyValues(beanName, bean, beanDefinition); 
  20.             // 執(zhí)行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置處理方法 
  21.             bean = initializeBean(beanName, bean, beanDefinition); 
  22.         } catch (Exception e) { 
  23.             throw new BeansException("Instantiation of bean failed", e); 
  24.         } 
  25.  
  26.         // 注冊(cè)實(shí)現(xiàn)了 DisposableBean 接口的 Bean 對(duì)象 
  27.         registerDisposableBeanIfNecessary(beanName, bean, beanDefinition); 
  28.  
  29.         // 判斷 SCOPE_SINGLETON、SCOPE_PROTOTYPE 
  30.         if (beanDefinition.isSingleton()) { 
  31.             registerSingleton(beanName, bean); 
  32.         } 
  33.         return bean; 
  34.     } 
  35.  
  36.     /** 
  37.      * 在設(shè)置 Bean 屬性之前,允許 BeanPostProcessor 修改屬性值 
  38.      * 
  39.      * @param beanName 
  40.      * @param bean 
  41.      * @param beanDefinition 
  42.      */ 
  43.     protected void applyBeanPostProcessorsBeforeApplyingPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) { 
  44.         for (BeanPostProcessor beanPostProcessor : getBeanPostProcessors()) { 
  45.             if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor){ 
  46.                 PropertyValues pvs = ((InstantiationAwareBeanPostProcessor) beanPostProcessor).postProcessPropertyValues(beanDefinition.getPropertyValues(), bean, beanName); 
  47.                 if (null != pvs) { 
  48.                     for (PropertyValue propertyValue : pvs.getPropertyValues()) { 
  49.                         beanDefinition.getPropertyValues().addPropertyValue(propertyValue); 
  50.                     } 
  51.                 } 
  52.             } 
  53.         } 
  54.     }   
  55.  
  56.     // ... 
  • AbstractAutowireCapableBeanFactory#createBean 方法中有這一條新增加的方法調(diào)用,就是在設(shè)置 Bean 屬性之前,允許 BeanPostProcessor 修改屬性值 的操作 applyBeanPostProcessorsBeforeApplyingPropertyValues
  • 那么這個(gè) applyBeanPostProcessorsBeforeApplyingPropertyValues 方法中,首先就是獲取已經(jīng)注入的 BeanPostProcessor 集合并從中篩選出繼承接口 InstantiationAwareBeanPostProcessor 的實(shí)現(xiàn)類。
  • 最后就是調(diào)用相應(yīng)的 postProcessPropertyValues 方法以及循環(huán)設(shè)置屬性值信息,beanDefinition.getPropertyValues().addPropertyValue(propertyValue);

五、測(cè)試

 

1. 事先準(zhǔn)備

配置 Dao

  1. @Component 
  2. public class UserDao { 
  3.  
  4.     private static Map<String, String> hashMap = new HashMap<>(); 
  5.  
  6.     static { 
  7.         hashMap.put("10001""小傅哥,北京,亦莊"); 
  8.         hashMap.put("10002""八杯水,上海,尖沙咀"); 
  9.         hashMap.put("10003""阿毛,香港,銅鑼灣"); 
  10.     } 
  11.  
  12.     public String queryUserName(String uId) { 
  13.         return hashMap.get(uId); 
  14.     } 
  15.  
  • 給類配置上一個(gè)自動(dòng)掃描注冊(cè) Bean 對(duì)象的注解 @Component,接下來會(huì)把這個(gè)類注入到 UserService 中。

注解注入到 UserService

  1. @Component("userService"
  2. public class UserService implements IUserService { 
  3.  
  4.     @Value("${token}"
  5.     private String token; 
  6.  
  7.     @Autowired 
  8.     private UserDao userDao; 
  9.  
  10.     public String queryUserInfo() { 
  11.         try { 
  12.             Thread.sleep(new Random(1).nextInt(100)); 
  13.         } catch (InterruptedException e) { 
  14.             e.printStackTrace(); 
  15.         } 
  16.         return userDao.queryUserName("10001") + "," + token; 
  17.     }     
  18.  
  19.     // ... 
  • 這里包括了兩種類型的注入,一個(gè)是占位符注入屬性信息 @Value("${token}"),另外一個(gè)是注入對(duì)象信息 @Autowired

2. 屬性配置文件

token.properties

  1. token=RejDlI78hu223Opo983Ds 

spring.xml

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.        xmlns:context="http://www.springframework.org/schema/context" 
  5.        xsi:schemaLocation="http://www.springframework.org/schema/beans 
  6.           http://www.springframework.org/schema/beans/spring-beans.xsd 
  7.    http://www.springframework.org/schema/context"> 
  8.  
  9.     <bean class="cn.bugstack.springframework.beans.factory.PropertyPlaceholderConfigurer"
  10.         <property name="location" value="classpath:token.properties"/> 
  11.     </bean> 
  12.  
  13.     <context:component-scan base-package="cn.bugstack.springframework.test.bean"/> 
  14.  
  15. </beans> 

 

在 spring.xml 中配置了掃描屬性信息和自動(dòng)掃描包路徑范圍。

3. 單元測(cè)試

  1. @Test 
  2. public void test_scan() { 
  3.     ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml"); 
  4.     IUserService userService = applicationContext.getBean("userService", IUserService.class); 
  5.     System.out.println("測(cè)試結(jié)果:" + userService.queryUserInfo()); 
  • 單元測(cè)試時(shí)候就可以完整的測(cè)試一個(gè)類注入到 Spring 容器,同時(shí)這個(gè)屬性信息也可以被自動(dòng)掃描填充上。

測(cè)試結(jié)果

測(cè)試結(jié)果:小傅哥,北京,亦莊,RejDlI78hu223Opo983Ds

Process finished with exit code 0

《Spring 手?jǐn)]專欄》:通過注解給屬性注入配置和Bean對(duì)象

  • 從測(cè)試結(jié)果可以看到現(xiàn)在我們的使用方式已經(jīng)通過了,有自動(dòng)掃描類,有注解注入屬性。這與使用 Spring 框架越來越像了。

六、總結(jié)

 

  • 從整個(gè)注解信息掃描注入的實(shí)現(xiàn)內(nèi)容來看,我們一直是圍繞著在 Bean 的生命周期中進(jìn)行處理,就像 BeanPostProcessor 用于修改新實(shí)例化 Bean 對(duì)象的擴(kuò)展點(diǎn),提供的接口方法可以用于處理 Bean 對(duì)象實(shí)例化前后進(jìn)行處理操作。而有時(shí)候需要做一些差異化的控制,所以還需要繼承 BeanPostProcessor 接口,定義新的接口 InstantiationAwareBeanPostProcessor 這樣就可以區(qū)分出不同擴(kuò)展點(diǎn)的操作了。
  • 像是接口用 instanceof 判斷,注解用 Field.getAnnotation(Value.class); 獲取,都是相當(dāng)于在類上做的一些標(biāo)識(shí)性信息,便于可以用一些方法找到這些功能點(diǎn),以便進(jìn)行處理。所以在我們?nèi)粘i_發(fā)設(shè)計(jì)的組件中,也可以運(yùn)用上這些特點(diǎn)。
  • 當(dāng)你思考把你的實(shí)現(xiàn)融入到一個(gè)已經(jīng)細(xì)分好的 Bean 生命周期中,你會(huì)發(fā)現(xiàn)它的設(shè)計(jì)是如此的好,可以讓你在任何初始化的時(shí)間點(diǎn)上,任何面上,都能做你需要的擴(kuò)展或者改變,這也是我們做程序設(shè)計(jì)時(shí)追求的靈活性。

原文鏈接:https://mp.weixin.qq.com/s/GNLA10AimmxUSZ0VoDI_xA

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久精品一区 | 亚洲 欧美 日韩 在线 | 亚洲精品高潮呻吟久久av | 一色屋精品久久久久久久久久 | 99精品视频在线 | 日韩av一区二区在线观看 | av高清在线看 | 亚洲精品视频在线 | 久久久精品久久久 | 亚洲综合区 | av在线免费网址 | 国产玖玖 | 亚洲激情精品 | 亚洲综合影院 | 成人黄色在线 | 亚洲乱码日产精品一二三 | 日韩精品第一页 | 日本精品在线观看视频 | 黄视频在线免费看 | 依人成人综合网 | 日韩精品在线一区 | 亚洲国产网站 | 欧美日韩第一页 | 欧美在线观看黄 | 天天操天天干天天 | 国产精品99在线观看 | 久久久久久久av | 亚洲欧美自拍偷拍 | 中文字幕99| 亚洲第一福利视频 | 色婷婷一区 | 欧美日韩综合 | 国产一区二区精品在线 | 欧美电影免费观看网站 | 日韩不卡一区二区三区 | 九一视频在线免费观看 | 黄色短片免费看 | 一区二区三区在线视频播放 | 高清在线一区二区 | 精品视频免费在线 | 久草在线资源福利站 |