1. 程式人生 > >spring閱讀原始碼後的個人理解

spring閱讀原始碼後的個人理解

spring閱讀原始碼後的個人理解

       spring是java web的一套開源框架,可以理解為一個輕量級容器。它的核心有二分別是:IoC,AOP。
       IoC(Inversion of Control):控制反轉,之前很不理解“控制反轉”的意思,現在我給它個通俗的解釋,其實就是將我們的bean物件交給spring去管理了,這也就是開頭我為什麼會說spring是個容器了。bean翻譯成漢語就是“豆子”,那麼spring就類似於一個碗來盛我們的bean,並且我們在開發種各種服務之間的呼叫不需要我們去手動new物件來進行呼叫,spring會在需要的時候來例項化物件提供給我們使用。談到IoC不得不說它之中的一個核心 DI(依賴注入)。

步驟:A:啟動Spring容器;B:從Spring容器中把物件取出來;C:最後,物件呼叫實際的業務方法。 

A:啟動Spring容器:
在類路徑下尋找配置檔案來例項化容器:ApplicationContext context = new ClassPathXmlApplicationContext("配置檔案類路徑");

通過這種方式載入。需要將spring配置檔案放到當前專案的classpath路徑下。classpath路徑指的是當前專案的src目錄,該目錄是java原始檔的存放位置。



在檔案系統路徑下尋找配置檔案來例項化容器:ApplicationContext context = new FileSystemXmlApplicationContext("配置檔案系統路徑"); 



注:經常採用第一種方式啟動Spring容器。

B:從Spring容器中把物件取出來:

context.getBean("配置檔案中bean的id"); 如:HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");

C:物件呼叫實際的業務方法:

helloWorld.hello(); 

並且spring種獲取的getBean()均是單例模式的。
注意:可以看下單例模式:懶漢,惡漢的區別,並且能夠自己寫出來

        synchronized (this.mergedBeanDefinitions) {
        RootBeanDefinition mbd = null;

        // Check with full lock now in order to enforce the same merged instance.
        if (containingBd == null) {
            mbd = this.mergedBeanDefinitions.get(beanName);
        }

        if (mbd == null) {
            if (bd.getParentName() == null) {
                // Use copy of given root bean definition.
                if (bd instanceof RootBeanDefinition) {
                    mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                }
                else {
                    mbd = new RootBeanDefinition(bd);
                }
            }
            else {
                // Child bean definition: needs to be merged with parent.
                BeanDefinition pbd;
                try {
                    String parentBeanName = transformedBeanName(bd.getParentName());
                    if (!beanName.equals(parentBeanName)) {
                        pbd = getMergedBeanDefinition(parentBeanName);
                    }
                    else {
                        if (getParentBeanFactory() instanceof ConfigurableBeanFactory) {
                            pbd = ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(parentBeanName);
                        }
                        else {
                            throw new NoSuchBeanDefinitionException(bd.getParentName(),
                                    "Parent name '" + bd.getParentName() + "' is equal to bean name '" + beanName +
                                    "': cannot be resolved without an AbstractBeanFactory parent");
                        }
                    }
                }
                catch (NoSuchBeanDefinitionException ex) {
                    throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                            "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
                }
                // Deep copy with overridden values.
                mbd = new RootBeanDefinition(pbd);
                mbd.overrideFrom(bd);
            }

            // Set default singleton scope, if not configured before.
            if (!StringUtils.hasLength(mbd.getScope())) {
                mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
            }

            // A bean contained in a non-singleton bean cannot be a singleton itself.
            // Let's correct this on the fly here, since this might be the result of
            // parent-child merging for the outer bean, in which case the original inner bean
            // definition will not have inherited the merged outer bean's singleton status.
            if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
                mbd.setScope(containingBd.getScope());
            }

            // Only cache the merged bean definition if we're already about to create an
            // instance of the bean, or at least have already created an instance before.
            if (containingBd == null && isCacheBeanMetadata()) {
                this.mergedBeanDefinitions.put(beanName, mbd);
            }
        }

        return mbd;
    }

       DI(Dependency Injection)依賴注入,IoC的核心,IoC就是基於DI的。可以參考這csdn這篇文章
依賴注入的理解,一般知道它的兩種注入方式:通過註解,xml配置即可。上邊連結中提到的BeanFactory 和 ApplicationContext補充一點區別就是:BeanFactory會懶載入,需要什麼bean例項化什麼bean,而ApplicationContext會例項化所有的bean
       AOP(Aspect Oriented Programming)面向切面程式設計,屬於一種程式設計正規化跟我們提到的:面向物件程式設計,面向介面程式設計,面向過程程式設計,函數語言程式設計一樣同屬於一種程式設計正規化即就是定義了一種程式設計規範,每個程式設計正規化都存在其優缺點,並且使用的場景不一樣。我們實際開發過程中一個 controller,service,dao屬於一個模組,所有模組累加起來構成了一個專案。所有的模組可以看成是橫向劃分的(好多個豆腐塊摞在了一起)AOP的概念呢就是將這些個橫著的豆腐塊豎著切一刀。比如我們的事物控制層常常放在service層,就是從service層豎著切了一刀。 再比如果某幾個方法需要判斷一下當前使用者的許可權。最常用的是寫一個公共方法然後再在那幾個方法中進行呼叫即可。利用spring中的AOP則不需要在業務方法中新增任何程式碼,只需要進行方法切面加入許可權相當於在方法前進行攔截。
springMVC流程工作流程:
1、使用者傳送請求至前端控制器DispatcherServlet
2、DispatcherServlet收到請求呼叫HandlerMapping處理器對映器。
3、處理器對映器根據請求url找到具體的處理器,生成處理器物件及處理器攔截器(二者組成HandlerExecutionChain),並將其一併返回給 DispatcherServlet。
4、DispatcherServlet通過HandlerAdapter處理器介面卡呼叫處理器
5、執行處理器(Controller,也叫後端控制器)。
6、Controller執行完成返回ModelAndView
7、HandlerAdapter將controller執行結果ModelAndView返回給DispatcherServlet
8、DispatcherServlet將ModelAndView傳給ViewReslover檢視解析器
9、ViewReslover解析後返回具體View
10、DispatcherServlet對View進行渲染檢視(即將模型資料填充至檢視中)。
11、DispatcherServlet對使用者進行響應
DispatcherServlet是springMVC的核心,它的原始碼應該好好看下,包括它是什麼地方spring與tomcat容器的上下文進行繫結的 HandlerMapping是兩種處理請求和cotroller是如何對映的:xml,依賴注入。
spring原始碼解析