前言
華夏ERP基于SpringBoot框架和SaaS模式,立志為中小企業(yè)提供開源好用的ERP軟件,目前專注進銷存+財務+生產(chǎn)功能。主要模塊有零售管理、采購管理、銷售管理、倉庫管理、財務管理、報表查詢、系統(tǒng)管理等。支持預付款、收入支出、倉庫調(diào)撥、組裝拆卸、訂單等特色功能。擁有庫存狀況、出入庫統(tǒng)計等報表。同時對角色和權限進行了細致全面的控制,精確到每個按鈕和菜單。
項目總述
- 很多人說華夏ERP(英文名:jshERP)是目前人氣領先的國產(chǎn)ERP系統(tǒng)
- 雖然目前只有進銷存+財務+生產(chǎn)的功能,但后面會推出ERP的全部功能,有興趣請幫點一下 Star 哦
- 演示地址:http://47.116.69.14 演示賬號:jsh,密碼:123456
開發(fā)初衷
- 華夏ERP立志為中小企業(yè)提供開源好用的ERP軟件,降低企業(yè)的信息化成本
- 個人開發(fā)者也可以使用華夏ERP進行二次開發(fā),加快完成開發(fā)任務 關注Java項目分享
- 初學JAVA的小伙伴可以下載源代碼來進行學習交流
技術框架
- 核心框架:SpringBoot 2.0.0
- 持久層框架:Mybatis 1.3.2
- 日志管理:Log4j 2.10.0
- JS框架:Jquery 1.8.0
- UI框架: EasyUI 1.9.4
- 模板框架: AdminLTE 2.4.0
- 項目管理框架: Maven 3.2.3
- API接口框架: swagger2.7.0(ip:port/doc.html)
開發(fā)環(huán)境
建議開發(fā)者使用以下環(huán)境,可以避免版本不一致帶來的問題
- IDE: IntelliJ IDEA 2017+
- DB: Mysql5.7+
- JDK: JDK1.8
- Maven: Maven3.2.3+
服務器環(huán)境
- 數(shù)據(jù)庫服務器:Mysql5.7+
- JAVA平臺: JRE1.8
- 操作系統(tǒng):Windows、Linux等
開源說明
- 本系統(tǒng)100%開源,遵守GPL-3.0協(xié)議
系統(tǒng)美圖
- 首頁
- 零售管理
- 采購管理
- 銷售管理
- 倉庫管理
- 財務管理
- 報表查詢
- 商品管理
- 基本資料
- 系統(tǒng)管理
源碼資料獲取方式:關注小編+轉(zhuǎn)發(fā)文章+私信【 0626】免費獲?。。。。?/h1>一、什么是Spring?談談你對IOC和AOP的理解。
Spring: 是一個企業(yè)級java應用框架,他的作用主要是簡化軟件的開發(fā)以及配置過程,簡化項目部署環(huán)境。Spring的有點:1、Spring低侵入設計,對業(yè)務代碼的污染非常低。2、Spring的DI機制將對象之間的關系交由框架處理,減少組件的耦合。3、Spring提供了AOP技術,支持將一些通用的功能進行集中式管理,從而提供更好的復用。4、Spring對于主流框架提供了非常好的支持。IOC就是控制反轉(zhuǎn),指創(chuàng)建對象的控制權轉(zhuǎn)移給Spring來進行管理。簡單來說,就是應用不用去new對象了,而全部交由Spring自動生產(chǎn)。IOC有三種注入方式:1、 構造器注入 2、setter方法注入 3、根據(jù)注解注入。AOP 面向切面。用于將那些與業(yè)務無關,但卻能對多個對象產(chǎn)生影響的公共行為。抽取并封裝成一個可重用的模塊。AOP的核心就是動態(tài)代理。JDK的動態(tài)代理 和CGLIB動態(tài)代理。
二、Spring容器的啟動流程是怎么樣的?
使用AnnotationConfigApplicationContext 來跟蹤一下啟動流程: this(); 初始化reader和scannerscan(basePackages); 使用scanner組件掃描basePackage下的所有對象,將配置類的BeanDefinition注冊到容器中。refresh(); 刷新容器。prepareRefresh 刷新前的預處理obtainFreshBeanFactory: 獲取在容器初始化時創(chuàng)建的BeanFactoryprepareBeanFactory: BeanFactory的預處理工作,會向容器中添加一些組件。postProcessBeanFactory: 子類重寫該方法,可以實現(xiàn)在BeanFactory創(chuàng)建并預處理完成后再做進一步的設置。invokeBeanFactoryPostProcessors: 在BeanFactory初始化之后執(zhí)行BeanFactory的后處理器。
registerBeanPostProcessors: 向容器中注冊Bean的后處理器,他的主要作用就是干預Spring初始化Bean的流程,完成代理、自動注入、循環(huán)依賴等這些功能。initMessageSource: 初始化messagesource組件,主要用于國際化。initApplicationEventMulticaster: 初始化事件分發(fā)器onRefresh: 留給子容器,子類重寫的方法,在容器刷新的時候可以自定義一些邏輯。registerListeners: 注冊監(jiān)聽器。finishBeanFactoryInitialization: 完成BeanFactory的初始化,主要作用是初始化所有剩下的單例Bean。finishRefresh: 完成整個容器的初始化,發(fā)布BeanFactory容器刷新完成的事件。
三、Spring框架中Bean的創(chuàng)建過程是怎樣
的?首先,簡單來說,Spring框架中的Bean經(jīng)過四個階段: 實例化 -》 屬性賦值 -》初始化 -》 銷毀然后: 具體來說,Spring中Bean 經(jīng)過了以下幾個步驟:1、實例化: new xxx(); 兩個時機: 1、當客戶端向容器申請一個Bean時,2、當容器在初始化一個Bean時發(fā)現(xiàn)還需要依賴另一個Bean。 BeanDefinition 對象保存。-到底是new一個對象還是創(chuàng)建一個動態(tài)代理?2、設置對象屬性(依賴注入):Spring通過BeanDefinition找到對象依賴的其他對象,并將這些對象賦予當前對象。3、處理Aware接口:Spring會檢測對象是否實現(xiàn)了xxxAware接口,如果實現(xiàn)然后,就會調(diào)用對應的方法。BeanNameAware、BeanClassLoaderAware、BeanFactoryAware、ApplicationContextAware
4、BeanPostProcessor前置處理: 調(diào)用BeanPostProcessor的postProcessBeforeInitialization方法5、InitializingBean: Spring檢測對象如果實現(xiàn)了這個接口,就會執(zhí)行他的afterPropertiesSet()方法,定制初始化邏輯。6、init-method: 如果Spring發(fā)現(xiàn)Bean配置了這個屬性,就會調(diào)用他的配置方法,執(zhí)行初始化邏輯。@PostConstruct7、BeanPostProcessor后置處理: 調(diào)用BeanPostProcessor的postProcessAfterInitialization方法
到這里,這個Bean的創(chuàng)建過程就完成了, Bean就可以正常使用了。
8、DisposableBean: 當Bean實現(xiàn)了這個接口,在對象銷毀前就會調(diào)用destory()方法。9、destroy-method: @PreDestroy
四、Spring框架中的Bean是線程安全的嗎?
如果線程不安全,要如何處理?Spring容器本身沒有提供Bean的線程安全策略,因此,也可以說Spring容器中的Bean不是線程安全的。要如何處理線程安全問題,就要分情況來分析。Spring中的作用域: 1、 sington 2、prototype: 為每個Bean請求創(chuàng)建給實例。3、request:為每個request請求創(chuàng)建一個實例,請求完成后失效。 4、 session:與request是類似的。 5、global-session:全局作用域。對于線程安全問題:1> 對于prototype作用域,每次都是生成一個新的對象,所以不存在線程安全問題。2>sington作用域: 默認就是線程不完全的。但是對于開發(fā)中大部分的Bean,其實是無狀態(tài)的,不需要保證線程安全。所以在平常的MVC開發(fā)中,是不會有線程安全問題的。
無狀態(tài)表示這個實例沒有屬性對象, 不能保存數(shù)據(jù),是不變的類。比如: controller、service、dao有狀態(tài)表示示例是有屬性對象,可以保存數(shù)據(jù),是線程不安全的, 比如pojo.但是如果要保證線程安全,可以將Bean的作用域改為prototype 比如像 ModelView。另外還可以采用ThreadLocal來解決線程安全問題。ThreadLocal為每個線程保存一個副本變量, 每個線程只操作自己的副本變量。
五、Spring如何處理循環(huán)依賴問題?
循環(huán)依賴: 多個對象之間存在循環(huán)的引用關系,在初始化過程當中,就會出現(xiàn)”先有蛋還是先有雞”的問題。
一種是使用@Lazy注解: 解決構造方法造成的循環(huán)依賴問題另一種是使用三級緩存一級緩存:緩存最終的單例池對象: private final MapsingletonObjects = new ConcurrentHashMap(256);二級緩存:緩存初始化的對象:private final MapearlySingletonObjects = new ConcurrentHashMap(16);三級緩存:緩存對象的ObjectFactory: private final Map singletonFactories = new HashMap(16);
對于對象之間的普通引用,二級緩存會保存new出來的不完整對象,這樣當單例池中找到不依賴的屬性時,就可以先從二級緩存中獲取到不完整對象,完成對象創(chuàng)建建,在后續(xù)的依賴注入過程中,將單例池中對象地引用關系調(diào)整完成。三級緩存:如果引用的對象配置了AOP,那在單例池中最終就會需要注入動態(tài)代理對象,而不是原對象。而生成動態(tài)代理是要在對象初始化完成之后才開始的。于是Spring增加三級緩存,保存所有對象的動態(tài)代理配置信息。在發(fā)現(xiàn)有循環(huán)依賴時,將這個對象的動態(tài)代理信息獲取出來,提前進行AOP,生成動態(tài)代理。核心代碼就在DefaultSingletonBeanRegistry的getSingleton方法當中。
protected Object getSingleton(String beanName, boolean allowEarlyReference){// Quick check for existing instance without full singleton lockObject singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null &&isSingletonCurrentlyInCreation(beanName)) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {synchronized (this.singletonObjects) {// Consistent creation of early reference within fullsingleton locksingletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {singletonObject =this.earlySingletonObjects.get(beanName);if (singletonObject == null) {ObjectFactory singletonFactory =this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject =singletonFactory.getObject();this.earlySingletonObjects.put(beanName,singletonObject);this.singletonFactories.remove(beanName}}}}}return singletonObject;}
六、Spring如何處理事務?
Spring當中支持編程式事務管理和聲明式事務管理兩種方式:1、編程式事務可以使用TransactionTemplate。2、聲明式事務: 是Spring在AOP基礎上提供的事務實現(xiàn)機制。他的最大優(yōu)點就是不需要在業(yè)務代碼中添加事務管理的代碼,只需要在配置文件中做相關的事務規(guī)則聲明就可以了。但是聲明式事務只能針對方法級別,無法控制代碼級別的事務管理理。Spring中對事務定義了不同的傳播級別: Propagation1、 PROPAGATION_REQUIRED:默認傳播行為。 如果當前沒有事務,就創(chuàng)建一新事務,如果當前存在事務,就加入到事務中。2、PROPAGATION_SUPPORTS: 如果當前存在事務,就加入到該事務。如果當前不存在事務,就以非事務的方式運行。
3、PROPAGATION_MANDATORY: 如果當前存在事務,就加入該事務。如果當前不存在事務,就拋出異常。
4、PROPAGATION_REQUIRES_NEW: 無論當前存不存在事務,都創(chuàng)建新事務進行執(zhí)行。
5、PROPAGATION_NOT_SUPPORTED: 以非事務方式運行。如果當前存在事務必,就將當前事務掛起。
6、PROPAGATION_NEVER : 以非事務的方式運行。如果當前存在事務,就拋出異議常。
7、PROPAGATION_NESTED: 如果當前存在事務,則在嵌套事務內(nèi)執(zhí)行;如果當前沒有事務,則按REQUEIRED屬性執(zhí)行。Spring中事務的隔離級別:1、ISOLATION_DEFAULT: 使用數(shù)據(jù)庫默認的事務隔離級別。2、ISOLATION_READ_UNCOMMITTED: 都未提交。允許事務在執(zhí)行過程中,必須取其他事務未提交的數(shù)據(jù)。3、ISOLATION_READ_COMMITTED: 讀已提交。允許事務在執(zhí)行過程中,讀取其他事務已經(jīng)提交的數(shù)據(jù)。4、ISOLATION_REPEATABLE_READ: 可重復讀。 在同一個事務內(nèi),任意時刻的查詢結(jié)果是一致的。5、ISOLATION_SERIALIZABLE: 所有事務依次執(zhí)行。
七、SpringMVC中的控制器是不是單例模
式?如果是,如何保證線程安全?控制器是單例模式。單例模式下就會有線程安全問題。Spring中保證線程安全的方法1、將scop設置成非singleton。 prototype, request。2、最好的方式是將控制器設計成無狀態(tài)模式。在控制器中,不要攜帶數(shù)據(jù)。但是可以引用無狀態(tài)的service和dao。