1. 程式人生 > >Java Spring IOC 框架原理解析

Java Spring IOC 框架原理解析

     在 Spring的某個版本之後,它就放棄了直接使用XmlBeanFactory .現在面向的企業級IOC運用都是ApplicationContext結尾的容器,比如ClassPathXmlApplicationContext,XmlWebApplicationContext,GenericApplicationContext等。

     但實際上這些類繁瑣負載,並且增加了平常開發中不必須要的東西。實際上一般還是用XmlBeanFactory這種簡潔方式。

        ClassPathResource resource=new ClassPathResource("Beans.xml");           BeanFactory context=new DefaultListableBeanFactory();           BeanDefinitionReader bdr=new XmlBeanDefinitionReader((BeanDefinitionRegistry) context);           bdr.loadBeanDefinitions(resource);

        Student student = (Student) context.getBean("student");         System.out.println(student.toString());         

       XmlBeaenDefinitionReader利用beanfactory 來載入裝配Bean以及Bean例項化類以及屬性值等等。

        XmlBeaenDefinitionReader呼叫loadBeanDefinitions整個過程解析了Beans.XML整個配置檔案裡的所有配置的東西。

        通過BeanName,GenericBeanDefinition的Map形式儲存。

        當通過 context.getBean("student");去獲取類例項的時候,他首先會去beanMapDefinition裡面獲取beanname 對應的genericbeandefinition然後轉換成rootbeandefinition 。

        下面的執行過程是:

               createbean->docreate->createBeanInstance->populateBean->applyPropertyValues 最後返回相對應的bean例項。

              篩選類屬性核心程式碼:

private CachedIntrospectionResults(Class<?> beanClass) throws BeansException {         try {             if (logger.isTraceEnabled()) {                 logger.trace("Getting BeanInfo for class [" + beanClass.getName() + "]");             }

            BeanInfo beanInfo = null;             for (BeanInfoFactory beanInfoFactory : beanInfoFactories) {                 beanInfo = beanInfoFactory.getBeanInfo(beanClass);                 if (beanInfo != null) {                     break;                 }             }             if (beanInfo == null) {                 // If none of the factories supported the class, fall back to the default                 beanInfo = (shouldIntrospectorIgnoreBeaninfoClasses ?                         Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO) :                         Introspector.getBeanInfo(beanClass));             }             this.beanInfo = beanInfo;

            if (logger.isTraceEnabled()) {                 logger.trace("Caching PropertyDescriptors for class [" + beanClass.getName() + "]");             }             this.propertyDescriptorCache = new LinkedHashMap<>();

            // This call is slow so we do it once.             PropertyDescriptor[] pds = this.beanInfo.getPropertyDescriptors();             for (PropertyDescriptor pd : pds) {                 if (Class.class == beanClass &&                         ("classLoader".equals(pd.getName()) ||  "protectionDomain".equals(pd.getName()))) {                     // Ignore Class.getClassLoader() and getProtectionDomain() methods - nobody needs to bind to those                     continue;                 }                 if (logger.isTraceEnabled()) {                     logger.trace("Found bean property '" + pd.getName() + "'" +                             (pd.getPropertyType() != null ? " of type [" + pd.getPropertyType().getName() + "]" : "") +                             (pd.getPropertyEditorClass() != null ?                                     "; editor [" + pd.getPropertyEditorClass().getName() + "]" : ""));                 }                 pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);                 this.propertyDescriptorCache.put(pd.getName(), pd);             }

            // Explicitly check implemented interfaces for setter/getter methods as well,             // in particular for Java 8 default methods...             Class<?> clazz = beanClass;             while (clazz != null) {                 Class<?>[] ifcs = clazz.getInterfaces();                 for (Class<?> ifc : ifcs) {                     BeanInfo ifcInfo = Introspector.getBeanInfo(ifc, Introspector.IGNORE_ALL_BEANINFO);                     PropertyDescriptor[] ifcPds = ifcInfo.getPropertyDescriptors();                     for (PropertyDescriptor pd : ifcPds) {                         if (!this.propertyDescriptorCache.containsKey(pd.getName())) {                             pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);                             this.propertyDescriptorCache.put(pd.getName(), pd);                         }                     }                 }                 clazz = clazz.getSuperclass();             }

            this.typeDescriptorCache = new ConcurrentReferenceHashMap<>();         }         catch (IntrospectionException ex) {             throw new FatalBeanException("Failed to obtain BeanInfo for class [" + beanClass.getName() + "]", ex);         }     }