自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

萬人之?dāng)常ㄟ^注解給屬性注入配置和Bean對象

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

[[415213]]

本文轉(zhuǎn)載自微信公眾號「bugstack蟲洞?!梗髡咝「蹈?。轉(zhuǎn)載本文請聯(lián)系bugstack蟲洞棧公眾號。

一、前言

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

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

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

二、目標(biāo)

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

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

三、方案

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

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

四、實(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 

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

圖 15-2

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

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

定義解析字符串接口

cn.bugstack.springframework.util.StringValueResolver

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

填充字符串

  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個注解在我們?nèi)粘J褂?Spring 也是非常常見的,注入對象、注入屬性,而 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 的一個用于在 Bean 對象實(shí)例化完成后,設(shè)置屬性操作前的處理屬性信息的類和操作方法。只有實(shí)現(xiàn)了 BeanPostProcessor 接口才有機(jī)會在 Bean 的生命周期中處理初始化信息
  • 核心方法 postProcessPropertyValues,主要用于處理類含有 @Value、@Autowired 注解的屬性,進(jìn)行屬性信息的提取和設(shè)置。
  • 這里需要注意一點(diǎn)因?yàn)槲覀冊?AbstractAutowireCapableBeanFactory 類中使用的是 CglibSubclassingInstantiationStrategy 進(jìn)行類的創(chuàng)建,所以在 AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues 中需要判斷是否為 CGlib 創(chuàng)建對象,否則是不能正確拿到類信息的。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 對象 
  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.         // 注冊實(shí)現(xiàn)了 DisposableBean 接口的 Bean 對象 
  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
  • 那么這個 applyBeanPostProcessorsBeforeApplyingPropertyValues 方法中,首先就是獲取已經(jīng)注入的 BeanPostProcessor 集合并從中篩選出繼承接口 InstantiationAwareBeanPostProcessor 的實(shí)現(xiàn)類。
  • 最后就是調(diào)用相應(yīng)的 postProcessPropertyValues 方法以及循環(huán)設(shè)置屬性值信息,beanDefinition.getPropertyValues().addPropertyValue(propertyValue);

五、測試

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.  
  • 給類配置上一個自動掃描注冊 Bean 對象的注解 @Component,接下來會把這個類注入到 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.     // ... 
  • 這里包括了兩種類型的注入,一個是占位符注入屬性信息 @Value("${token}"),另外一個是注入對象信息 @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 中配置了掃描屬性信息和自動掃描包路徑范圍。

3. 單元測試

  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("測試結(jié)果:" + userService.queryUserInfo()); 
  • 單元測試時候就可以完整的測試一個類注入到 Spring 容器,同時這個屬性信息也可以被自動掃描填充上。

測試結(jié)果

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

Process finished with exit code 0

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

六、總結(jié)

 

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

 

責(zé)任編輯:武曉燕 來源: bugstack蟲洞棧
相關(guān)推薦

2021-06-03 07:55:12

技術(shù)

2023-07-11 09:14:12

Beanquarkus

2021-07-28 07:53:19

配置Bean掃描

2009-06-15 17:48:32

Spring注解注入屬性

2017-10-15 21:19:19

科技盛會

2013-06-20 09:30:41

華為數(shù)據(jù)中心萬人桌面云華為

2010-01-06 09:16:10

MySQL

2021-11-11 11:38:56

Robinhood數(shù)據(jù)泄露網(wǎng)絡(luò)攻擊

2018-10-16 09:35:25

Facebook攻擊漏洞

2010-09-09 15:16:03

郭臺銘

2020-02-03 19:04:50

10萬人場館畫座位

2009-03-10 08:20:35

鴻海招募軟件代工

2011-11-02 09:20:26

華為云計(jì)算

2022-02-19 07:41:36

Bean注解項(xiàng)目

2012-06-01 14:46:13

華為裁員

2023-08-29 22:43:53

2023-08-31 00:03:28

2018-12-07 09:50:36

裁員失業(yè)中年人

2009-11-30 09:17:00

IBM員工數(shù)量

2010-05-11 10:35:56

IT企業(yè)招聘
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號