導航:首頁 > 源碼編譯 > javaspring源碼

javaspring源碼

發布時間:2023-09-07 18:42:45

java,gradle編譯spring源碼出錯

同學,這個問題的原因找到了,因為3.2的版本比較久遠,很多類庫已經更新變化了,修改的方法就是到gradle 倉庫下的C:\Users\Administrator\.gradle\caches\artifacts-24\mole-metadata\com.lowagie\itext\4.2.2\ 找到ivy.xml 修改

將dependency org="com.itextpdf" name="itextpdf" rev="4.2.2" 修改為dependency dependency org="com.itextpdf" name="itextpdf" rev="5.2.0",
然後將使用了該類的AbstractPdfStamperView、AbstractPdfView的import com.itext 修改為 com.itextpdf。。。

具體原因及說明可以看 去http://www.bdtool.net/blog_356.html 查看。

⑵ 如何查看spring源碼

1.准備工作:在官網上下載了Spring源代碼之後,導入Eclipse,以方便查詢。
2.打開我們使用Spring的項目工程,找到Web.xml這個網站系統配置文件,在其中找到Spring的初始化信息:

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

由配置信息可知,我們開始的入口就這里ContextLoaderListener這個監聽器。
在源代碼中我們找到了這個類,它的定義是:
public class ContextLoaderListener extends ContextLoader
implements ServletContextListener {

/**
* Initialize the root web application context.
*/
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
if (this.contextLoader == null) {
this.contextLoader = this;
}
this.contextLoader.initWebApplicationContext(event.getServletContext());
}
...
}

該類繼續了ContextLoader並實現了監聽器,關於Spring的信息載入配置、初始化便是從這里開始了,具體其他閱讀另外寫文章來深入了解。
二、關於IOC和AOP
關於Spring IOC 網上很多相關的文章可以閱讀,那麼我們從中了解到的知識點是什麼?
1)IOC容器和AOP切面依賴注入是Spring是核心。
IOC容器為開發者管理對象之間的依賴關系提供了便利和基礎服務,其中Bean工廠(BeanFactory)和上下文(ApplicationContext)就是IOC的表現形式。BeanFactory是個介面類,只是對容器提供的最基本服務提供了定義,而DefaultListTableBeanFactory、XmlBeanFactory、ApplicationContext等都是具體的實現。
介面:

public interface BeanFactory {
//這里是對工廠Bean的轉義定義,因為如果使用bean的名字檢索IOC容器得到的對象是工廠Bean生成的對象,
//如果需要得到工廠Bean本身,需要使用轉義的名字來向IOC容器檢索
String FACTORY_BEAN_PREFIX = "&";
//這里根據bean的名字,在IOC容器中得到bean實例,這個IOC容器就象一個大的抽象工廠,用戶可以根據名字得到需要的bean
//在Spring中,Bean和普通的JAVA對象不同在於:
//Bean已經包含了我們在Bean定義信息中的依賴關系的處理,同時Bean是已經被放到IOC容器中進行管理了,有它自己的生命周期
Object getBean(String name) throws BeansException;
//這里根據bean的名字和Class類型來得到bean實例,和上面的方法不同在於它會拋出異常:如果根名字取得的bean實例的Class類型和需要的不同的話。
Object getBean(String name, Class requiredType) throws BeansException;
//這里提供對bean的檢索,看看是否在IOC容器有這個名字的bean
boolean containsBean(String name);
//這里根據bean名字得到bean實例,並同時判斷這個bean是不是單件,在配置的時候,默認的Bean被配置成單件形式,如果不需要單件形式,需要用戶在Bean定義信息中標注出來,這樣IOC容器在每次接受到用戶的getBean要求的時候,會生成一個新的Bean返回給客戶使用 - 這就是Prototype形式
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//這里對得到bean實例的Class類型
Class getType(String name) throws NoSuchBeanDefinitionException;
//這里得到bean的別名,如果根據別名檢索,那麼其原名也會被檢索出來
String[] getAliases(String name);
}

實現:
XmlBeanFactory的實現是這樣的:
public class XmlBeanFactory extends DefaultListableBeanFactory {
//這里為容器定義了一個默認使用的bean定義讀取器,在Spring的使用中,Bean定義信息的讀取是容器初始化的一部分,但是在實現上是和容器的注冊以及依賴的注入是分開的,這樣可以使用靈活的 bean定義讀取機制。
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
//這里需要一個Resource類型的Bean定義信息,實際上的定位過程是由Resource的構建過程來完成的。
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
//在初始化函數中使用讀取器來對資源進行讀取,得到bean定義信息。這里完成整個IOC容器對Bean定義信息的載入和注冊過程
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws
BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}

⑶ SpringBoot內置生命周期事件詳解 SpringBoot源碼(十)

SpringBoot中文注釋項目Github地址:扒派族

https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE

本篇接 SpringBoot事件監聽機制源碼分析(上) SpringBoot源碼(九)

溫故而知新,我們來簡單回顧一下上篇的內容,上一篇我們分析了 SpringBoot啟動時廣播生命周期事件的原理羨汪 ,現將關鍵步驟再濃縮總結下:

上篇文章的側重點是分析了SpringBoot啟動時廣播生命周期事件的原理,此篇文章我們再來詳細分析SpringBoot內置的7種生命周期事件的源碼。

分析SpringBoot的生命周期事件,我們先來看一張類結構圖:

由上圖可以看到事件類之間的關系:

EventObject 類是JDK的事件基類,可以說是所有Java事件類的基本,即所有的Java事件類都直接或間接繼承於該類,源碼如下:

可以看到 EventObject 類只有一個屬性 source ,這個屬性是用來記錄最初事件是發生在哪個類,舉個栗子,比如在SpringBoot啟動過程中會發射 ApplicationStartingEvent 事件,而這個事件最初是在 SpringApplication 類中發射的,因此 source 就是 SpringApplication 對象。

ApplicationEvent 繼承了DK的事件基類 EventObject 類,是Spring的事件基類,被所有Spring的具體事件類繼承,源碼如下:

可以看到 ApplicationEvent 有且僅有一個屬性 timestamp ,該屬性是用來記錄事件發生的時間。

SpringApplicationEvent 類繼承了Spring的事件基類 ApplicationEvent ,是所有SpringBoot內置生命周期事件的父類,源碼如下:

可以看到 SpringApplicationEvent 有且僅有一個屬性 args ,該屬性就是SpringBoot啟動時的命令行參數即標注 @SpringBootApplication 啟動類中 main 函數的參數。

接下來我們再來看一下 SpringBoot 內置生命周期事件即 SpringApplicationEvent 的具體子類們。

SpringBoot開始啟動時便會發布 ApplicationStartingEvent 事件,其發布時機在環境變數Environment或容器ApplicationContext創建前但在注冊 ApplicationListener 具體監聽器之後,標志標志 SpringApplication 開始啟動。

可以看到 事件多了一個 environment 屬性,我們不妨想一下,多了 environment 屬性的作用是啥?
答案就是 事件的 environment 屬性作用是利用事件發布訂閱機制,相應監聽器們可以從 事件中取出 environment 變數,然後我們可以為 environment 屬性增加屬性值或讀出 environment 變數中的值。

當SpringApplication已經開始啟動且環境變數 Environment 已經創建後,並且為環境變數 Environment 配置了命令行和 Servlet 等類型的環春弊境變數後,此時會發布 事件。

監聽 事件的第一個監聽器是 ConfigFileApplicationListener ,因為是 ConfigFileApplicationListener 監聽器還要為環境變數 Environment 增加 application.properties 配置文件中的環境變數;此後還有一些也是監聽 事件的其他監聽器監聽到此事件時,此時可以說環境變數 Environment 幾乎已經完全准備好了。

可以看到 事件多了個 類型的 context 屬性, context 屬性的作用同樣是為了相應監聽器可以拿到這個 context 屬性執行一些邏輯,具體作用將在 3.4.4 詳述。

事件在 ApplicationContext 容器創建後,且為 ApplicationContext 容器設置了 environment 變數和執行了 的初始化方法後但在bean定義載入前觸發,標志ApplicationContext已經初始化完畢。

同樣可以看到 ApplicationPreparedEvent 事件多了個 類型的 context 屬性,多了 context 屬性的作用是能讓監聽該事件的監聽器們能拿到 context 屬性,監聽器拿到 context 屬性一般有如下作用:

ApplicationPreparedEvent 事件在 ApplicationContext 容器已經完全准備好時但在容器刷新前觸發,在這個階段 bean 定義已經載入完畢還有 environment 已經准備好可以用了。

ApplicationStartedEvent 事件將在容器刷新後但 ApplicationRunner 和 CommandLineRunner 的 run 方法執行前觸發,標志 Spring 容器已經刷新,此時容器已經准備完畢了。

ApplicationReadyEvent 事件在調用完 ApplicationRunner 和 CommandLineRunner 的 run 方法後觸發,此時標志 SpringApplication 已經正在運行。

可以看到 ApplicationFailedEvent 事件除了多了一個 context 屬性外,還多了一個 Throwable 類型的 exception 屬性用來記錄SpringBoot啟動失敗時的異常。

ApplicationFailedEvent 事件在SpringBoot啟動失敗時觸發,標志SpringBoot啟動失敗。

此篇文章相對簡單,對SpringBoot內置的7種生命周期事件進行了詳細分析。我們還是引用上篇文章的一張圖來回顧一下這些生命周期事件及其用途:

由於有一些小夥伴們建議之前有些源碼分析文章太長,導致耐心不夠,看不下去,因此,之後的源碼分析文章如果太長的話,筆者將會考慮拆分為幾篇文章,這樣就比較短小了,比較容易看完,嘿嘿。

【源碼筆記】Github地址:

https://github.com/yuanmabiji/Java-SourceCode-Blogs

點贊搞起來,嘿嘿嘿!

公眾號【 源碼筆記 】專注於Java後端系列框架的源碼分析。

⑷ Spring事件監聽機制源碼解析

1.Spring事件監聽體系包括三個組件:事件、事件監聽器搜哪,事件廣播器。

事件:定義事件類型和事件源,需要繼承ApplicationEvent。

事件監聽器:用來監聽某一類的事件,並且執行具體業務邏輯,需要實現ApplicationListener 介面或者需要用@ListenerEvent(T)註解。好比觀察者模式中的觀察者。

事件多播器:負責廣播通知所有監聽器,所有的事件監聽判猛器都注冊在了事件多播器中。好比觀察者模式中的被觀察者。Spring容器默認生成的是同步事件多播器。可以自定義事件多播器,定義為非同步方式。

創建 的過程中,會執行refresh()中的()方法。該方法先獲取bean工廠,然後判斷工廠是否包含了beanName 為 applicationEventMulticaster的bean。如果包含了,則獲取該bean,賦值給applicationEventMulticaster 屬性。如果沒有,則創建一個 對象,並且賦值給 applicationEventMulticaster 。實現了源碼如下:

監聽器的注冊有兩種,通過實現 ApplicationListener介面或者添加@EventListener註解。

注冊的邏輯實現在refresh()中的registerListeners()方法裡面。第一步,先獲取當前ApplicationContext中已經添加的 applicationListeners(SpringMVC源碼中有用到),遍歷添加到多播器中。第二步,獲取實現了ApplicationListener介面的listenerBeanNames集合,添加至多掘漏橋播器中。第三步,判斷是否有早期事件,如果有則發起廣播。

思考一下,上面的代碼中第二步為啥添加的是listenerBeanName?

如果監聽器是懶載入的話(即有@Lazy 註解)。那麼在這個時候創建監聽器顯然是不對的,這個時候不能創建監聽器。所以添加監聽器到多播器的具體邏輯放在初始化具體的監聽器之後。通過 BeanPostProcessor 的介面實現。具體的實現類是 ApplicationListenerDetector 。這個類是在 refreah()中prepareBeanFactory()方法中添加的。代碼如下:

在創建 的構造方法中,會執行org.springframework.context.annotation.AnnotationConfigUtils#(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object) 方法。這個方法中會添加兩個 beanDefs, 代碼如下:

EventListenerMethodProcessor:事件監聽器的BeanFactory後置處理器,在前期會創建 DefaultEventListenerFactory ,後期在創建好Bean之後,根據 EventListener 屬性,調用DefaultEventListenerFactory創建具體的 。

DefaultEventListenerFactory:監聽器的創建工廠,用來創建 。

EventListenerMethodProcessor 的類繼承圖如下:

在refreash的()中會調用 org.springframework.context.event.EventListenerMethodProcessor#postProcessBeanFactory方法,獲取EventListenerFactory 類型的 Bean。代碼如下:

在 org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons 方法中,創建完所有的單例Bean 之後,會遍歷所有Bean是否實現了 SmartInitializingSingleton 介面。如果實現介面會執行該 Bean 的 afterSingletonsInstantiated() 方法。代碼如下:

org.springframework.context.event.EventListenerMethodProcessor#afterSingletonsInstantiated 中會調用私有方法 processBean()進行 ApplicationEventAdatper 的創建。代碼如下:

可以通過調用 org.springframework.context.support.AbstractApplicationContext#publishEvent(java.lang.Object, org.springframework.core.ResolvableType) 方法進行事件的調用。代碼如下:

中的 multicasEvent,invokeListener,doInvokeListener 三個方法代碼如下:

SpringMVC中就是通過Spring的事件機制進行九大組件的初始化。

監聽器定義在FrameworkServlet類中,作為內部類。代碼如下:

監聽器的添加在org.springframework.web.servlet.FrameworkServlet# 中進行。通過SourceFilteringListener進行包裝。添加代碼如下:

在refresh中的registerListeners方法進行添加,代碼如下:

在refresh中的finishRefresh()方法中,會調用publishEvnet(new ContextRefreshedEvent(this))發布事件。進行多播器廣播,代碼如下

最終會調到FrameworkServlet.this.onApplicationEvent(event)。

⑸ 如何在Eclipse中查看JDK以及Java框架的源碼

在Eclipse中查看JDK類庫的源代碼
設置:
1.點 「window」-> "Preferences" -> "Java" -> "Installed JRES"
2.此時"Installed JRES"右邊是列表窗格,列出了系統中的 JRE 環境,選擇你的JRE,然後點邊上的 "Edit...", 會出現一個窗口(Edit JRE)
3.選中rt.jar文件的這一項:「c:\program files\java\jre_1.5.0_06\lib\rt.jar」 點 左邊的「+」 號展開它
4.展開後,可以看到「Source Attachment:(none)」,點這一項,點右邊的按鈕「Source Attachment...」, 選擇你的JDK目錄下的 「src.zip」文件
5.一路點"ok",結束。
dt.jar是關於運行環境的類庫,主要是swing的包 tools.jar是關於一些工具的類庫 rt.jar包含了jdk的基礎類庫,也就是你在java doc裡面看到的所有的類的class文件

⑹ 學習JAVA的同學都是怎麼讀源碼的

剛參加工作那會,沒想過去讀源碼,更沒想過去改框架的源碼;總想著別人的框架應該是完美的、萬能的,應該不需要改;另外即使我改了源碼,怎麼樣讓我的改動生效了?項目中引用的不還是沒改的jar包嗎。回想起來覺得那時候的想法確實挺??

工作了一年多之後准備跳槽了,開始了一輪的面試,其中有幾個面試官就問到了相關的源碼問題:ArrayList、HashMap的底層實現,spring、mybatis的相關源碼。問源碼的面試一般就是回去等消息,然後就沒然後了。

那時候開始意識到,源碼這東西在之前的工作的中感受不到,但是在面試中好像面的還挺頻繁的,從此有意識的開始了jdk部分源碼的閱讀(主要是集合)。一開始看源碼,看的特別糙,知道個大概,知道ArrayList的底層實現是數組,HashMap的底層是散列表(數組+鏈表);更深入一點的擴容、hash碰撞等等就不知道了。

讀spring源碼起於工作中遇到了一個問題(springjdbcTemplate事務,各種詭異,包你醍醐灌頂!),排查一段時間最終是解決了,但過程讓我非常難受,各種上網查資料、各種嘗試,感覺就像大海撈針一樣,遙遙無期。我下定決心,我要看一看spring的源碼,於是我買了一本《spring源碼深度斗帶解析》,結合著這本書、打開著eclipse,開始了spring的源碼閱讀之旅。至此,讀源碼成了習慣,源碼已經進入了我的心裡。

後來,springboot的火熱,讓我也想蹭上一蹭,於是有了springboot的啟動源碼系列,雖然還在進行中,指侍但是我相信我能將其完成;工作中用到了shiro,我又結合著《跟我學shiro》將shiro的源碼看了個大概,有了shiro源碼系列博文,還差一篇認證與授權(應該很快就能面世),shiro源碼系列就封筆了。最近在搭建自己的後台管理系統,用到了quartz,集成的過程也遇到了一些問題,因此有了quartz的兩篇文章。

慢慢的,從一味的網上找資料變成了很多時候會從源碼中找答案。不求能讀太多的源碼,但願自己接觸的技術都能讀上一讀,路漫漫其修遠兮,吾將上下而求索!

大家為什麼要讀源碼?

很多人一定和我一樣的感受:源碼在工作中有用嗎?用處大嗎?很長一段時間內我也有這樣的疑問,認為哪些有事沒事扯源碼的人就是在裝,只是為了提高他們的逼格而已。

那為什麼我還要讀源碼呢?一剛開始為了面試,後來為了解決工作中的問題,再後來就是個人喜好了。說的好聽點是有匠人精神;說的委婉點是好奇(底層是怎麼實現的);說的不自信點是對黑盒的東西我用的沒底,怕用錯;說的簡單直白點是提升自我價值,為了更高的薪資待遇(這里對真正的技術迷說聲抱歉)。

源碼中我們可以學到很多東西,學習別人高效的代碼書寫、學習別人對設計模式的熟練使用、學習別人對整個架構的布局,等等。如果你還能找出其中的不足,那麼恭喜你,你要飛升了!會使用固然重要,但知道為什麼這么使用同樣重要。從模仿中學習,從模仿中創新。

讀源碼不像圍城(外面的人想進來,裡面的人想出去),它是外面的人不想進來,裡面的人不想出去;當我們跨進城內,你會發現(還是城外好,皮!)城內風光無限,源碼的海洋任我們遨遊!

首先我們要對我們的目標有所了解,知道她有什麼特點,有些什麼功能。對對方都還不了解,就想著進入別人的內心世界,那不是臭不要臉嘛,我們要做一個有著流氓心的紳士;對她有個大致的了解了,就可以發起攻勢,一舉拿下。

那麼怎麼樣了解了,方式有很多,我這里提供幾種,僅供參考

最好的方式就是官方參考指南,親生父母往往對孩子是最了解的,對孩子的描述也是最詳細的;比唯銷吵如SpringBootReferenceGuide就是對springboot最詳細的描述,怎麼樣使用springboot、springboot特性等等,通過此指南,springboot在你面前一覽無遺;

但是,springboot畢竟是外國人的孩子,如果英語不好,估計讀起來有點頭疼了,不過我們有google翻譯呀,咬咬牙也是能看的。源碼世界的丈母娘、老岳丈是非常慷慨的!

其次是書籍,國外優秀的有很多,國內也不乏好書,比較推薦此方式,自成體系,讓我們掌握的知識點不至於太散。這就是好比是源碼的閨蜜,對源碼非常了解,重點是挺大方,會盡全力幫助我們了解源碼。

再次就是博客,雖然可能覺得知識點比較散,但是針對某個知識點卻特別的細,對徹底掌握非常有幫助,園子內就有很多技術大牛,寫的博客自然也是非常棒,非常具有學習價值。當然還有社區、論壇、github、碼雲等等。這就是源碼的朋友圈,我們從中也能獲取到非常多關於源碼的信息。

設計模式的了解

優秀的框架、技術從不乏設計模式;jdk源碼中就應用了很多設計模式,比如IO流中的適配器模式與裝飾模式、GUI的觀察者模式、集合中的迭代器模式等等;spring源碼中也是用到了大量的設計模式。設計模式有什麼優點、各適用於什麼場景,不是本文的內容,需要我們大家自行去了解。

我們只需要對一些常用的設計模式有個大致了解,再去讀源碼是比較好的;不需要將23種設計模式都通讀,也不需要將常用設計模式完全理解透;對於全部通讀,我們時間有限,另外有些模式確實不太好理解、用的少,性價比不高,沒必要全部都讀。

推薦書籍:《HeadFirstDesignPatterns》(中文版:《HeadFirst設計模式》)、《Java與模式》;

另外我比較推薦的一種學習設計模式的方式是讀別人博客:java_my_life,劉偉技術博客,chenssy的設計模式;

設計模式之於源碼,就好比逛街購物之於女人,想順利勾搭源碼,我們需要好好掌握設計模式這個套路。

配合ide進行斷點追蹤

我們通過源碼的圈子對源碼的了解終究只是停在表面,終究還是沒有走進她的內心,接下來我就和大家分享下,我是如何走進她的內心的!

相信看過我的源碼博客的小夥伴都知道,我非常喜歡通過idea斷點來進行源碼追蹤,斷點追蹤源碼是我非常推薦的一種方式。斷點不僅可以用來調試我們的代碼,也可以用來調試我們用到的框架源碼。

面對未知的、茫茫多的源碼,我們往往沒有足夠的時間、經歷和耐心去通讀所有源碼,我們只需要去讀我們關注的部分即可(有人可能會說我都不關心,這?)。那為什麼要用斷掉調試的方式來跟源碼,而不是直接從源代碼入手去跟我們關注的部分呢?

嘗試過的小夥伴應該知道,如果我們對源碼不熟悉,直接通過源碼的方式去跟,一方面很容易迷路(多態,會有很多子類實現),不知道接下來跟哪一個,另一方面也很容易跟丟,當我們跟入的很深的時候,很有可能就忘記上一步跟到哪了。所以讀源碼的重要性淺顯易懂了。

閱讀全文

與javaspring源碼相關的資料

熱點內容
小奔運動app網路異常怎麼回事 瀏覽:447
php開啟壓縮 瀏覽:303
伺服器主機如何設置啟動 瀏覽:282
linux配置網路命令 瀏覽:774
一張照片怎麼製作視頻app 瀏覽:908
pythonweb和php 瀏覽:976
電腦伺服器地址ip地址 瀏覽:823
對矩陣壓縮是為了 瀏覽:910
setfacl命令 瀏覽:172
linux子系統中斷 瀏覽:342
linux查看進程ps 瀏覽:224
知識庫系統php 瀏覽:623
小波變換壓縮圖像python 瀏覽:151
阿里巴巴程序員怎麼月入百萬 瀏覽:173
如何使用國外伺服器 瀏覽:188
燃燈者pdf 瀏覽:468
編譯器用數學嗎 瀏覽:7
圖形化apk反編譯工具 瀏覽:48
考勤表加密怎麼辦 瀏覽:736
arj壓縮與解壓批處理怎麼寫 瀏覽:659