偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

萬人之?dāng)?,通過注解給屬性注入配置和Bean對象

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

[[415213]]

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

一、前言

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

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

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

二、目標(biāo)

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

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

三、方案

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

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

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

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

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 中,最主要的其實就是這行代碼的操作 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 是實現(xiàn)接口 InstantiationAwareBeanPostProcessor 的一個用于在 Bean 對象實例化完成后,設(shè)置屬性操作前的處理屬性信息的類和操作方法。只有實現(xiàn)了 BeanPostProcessor 接口才有機會在 Bean 的生命周期中處理初始化信息
  • 核心方法 postProcessPropertyValues,主要用于處理類含有 @Value、@Autowired 注解的屬性,進行屬性信息的提取和設(shè)置。
  • 這里需要注意一點因為我們在 AbstractAutowireCapableBeanFactory 類中使用的是 CglibSubclassingInstantiationStrategy 進行類的創(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.             // 實例化 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.         // 注冊實現(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 的實現(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é)

 

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

 

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

2021-06-03 07:55:12

技術(shù)

2023-07-11 09:14:12

Beanquarkus

2017-10-15 21:19:19

科技盛會

2009-06-15 17:48:32

Spring注解注入屬性

2021-07-28 07:53:19

配置Bean掃描

2010-01-06 09:16:10

MySQL

2013-06-20 09:30:41

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

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

華為云計算

2023-08-29 22:43:53

2023-08-31 00:03:28

2009-11-30 09:17:00

IBM員工數(shù)量

2018-12-07 09:50:36

裁員失業(yè)中年人

2012-06-01 14:46:13

華為裁員

2010-05-11 10:35:56

IT企業(yè)招聘

2010-09-14 09:11:00

點贊
收藏

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