java srping 原始碼分析 深入理解低層設計思想
原始碼分析---SPRING
- 專案介紹
1. Spring框架簡介
作為應用程式開發人員,您可以從Spring平臺中受益的示例如下:
使Java方法在資料庫事務中執行,而不必處理事務API。
使本地Java方法成為HTTP端點,而無需處理Servlet API。
使本地Java方法成為訊息處理程式,而無需處理JMS API。
使本地Java方法成為管理操作,而無需處理JMX API。
2.1依賴注入和控制反轉
Java應用程式 - 從受限制的嵌入式應用程式到n層伺服器端企業應用程式的寬鬆術語 - 通常由協作形成應用程式的物件組成。因此,應用程式中的物件彼此依賴。
Spring框架控制反轉(IoC)元件通過提供一種將不同元件組合成一個可以使用的完全工作的應用程式的形式化方法來解決這一問題。Spring Framework將形式化的設計模式編碼為可以整合到您自己的應用程式中的一流物件。許多組織和機構以這種方式使用Spring Framework來設計健壯,可維護的應用程式。
2.2框架模組
Spring框架是一個分層架構,它包含一系列的功能要素,並被分為大約20個模組,如下圖所示
Spring4框架圖
這些模組被總結為以下幾個部分:
Core Container核心容器
所述核心容器由以下部分組成spring-core, spring-beans,spring-context,spring-context-support,和spring-expression (彈簧表示式語言)模組。
的spring-core和spring-beans模組提供框架的基本零件,包括IOC和依賴注入特徵。這 BeanFactory是工廠模式的複雜實現。它消除了對程式化單例的需求,並允許您從實際程式邏輯中分離依賴項的配置和規範。
所述上下文(spring-context)模組建立由設定在固體基體上的核心和豆類模組:它是訪問一個框架式的方式是類似於一個JNDI登錄檔物件的裝置。Context模組從Beans模組繼承其功能,並新增對國際化(例如,使用資源包),事件傳播,資源載入以及通過例如Servlet容器透明建立上下文的支援。Context模組還支援Java EE功能,例如EJB,JMX和基本遠端處理。該ApplicationContext介面是語境模組的焦點。 spring-context-support支援將常見的第三方庫整合到Spring應用程式上下文中,用於快取(EhCache,Guava,JCache),郵件(JavaMail),排程(CommonJ,Quartz)和模板引擎(FreeMarker,JasperReports,Velocity)。
該spring-expression模組提供了一種功能強大的表示式語言,用於在執行時查詢和操作物件圖。它是JSP 2.1規範中指定的統一表達式語言(統一EL)的擴充套件。該語言支援設定和獲取屬性值,屬性賦值,方法呼叫,訪問陣列,集合和索引器的內容,邏輯和算術運算子,命名變數以及從Spring的IoC容器中按名稱檢索物件。它還支援列表投影和選擇以及常用列表聚合。
Data Access/Integration
JDBC模組提供了一個JDBC抽象層,它可以消除冗長的JDBC編碼和解析資料庫廠商特有的錯誤程式碼,這個模組包含了Spring對JDBC資料訪問進行封裝的所有類
ORM模組為流行的物件-關係對映API,如JPA、JDO、Hibernate、iBatis等,提供了一個互動層,利用ORM封裝包,可以混合使用所有Spring提供的特性進行O/R對映,如前邊提到的簡單宣告性事務管理
所述資料訪問/整合層由JDBC,ORM,OXM,JMS和交易模組。
該spring-jdbc模組提供了一個JDBC -abstraction層,無需進行繁瑣的JDBC編碼和解析資料庫供應商特定的錯誤程式碼。
該spring-tx模組支援 對實現特殊介面的類和所有POJO(普通舊Java物件)的類進行程式設計和宣告式事務管理。
該spring-orm模組為流行的物件關係對映 API 提供了整合層 ,包括JPA, JDO和Hibernate。使用該spring-orm模組,您可以將所有這些O / R對映框架與Spring提供的所有其他功能結合使用,例如前面提到的簡單宣告式事務管理功能。
該spring-oxm模組提供了一個抽象層,支援物件/ XML對映實現,如JAXB,Castor,XMLBeans,JiBX和XStream。
所述spring-jms模組(Java訊息服務)包含用於生成和使用訊息的功能。從Spring Framework 4.1開始,它提供了與spring-messaging模組的整合 。
Web
所述網路層由的spring-web,spring-webmvc,spring-websocket,和 spring-webmvc-portlet模組。
該spring-web模組提供基本的面向Web的整合功能,例如多部分檔案上載功能以及使用Servlet偵聽器和麵向Web的應用程式上下文初始化IoC容器。它還包含一個HTTP客戶端以及Spring的遠端支援的Web相關部分。
該spring-webmvc模組(也稱為Web-Servlet模組)包含Spring的模型 - 檢視 - 控制器(MVC)和Web應用程式的REST Web服務實現。Spring的MVC框架提供了域模型程式碼和Web表單之間的清晰分離,並與Spring Framework的所有其他功能整合在一起。
該spring-webmvc-portlet模組(也稱為Web-Portlet模組)提供了在Portlet環境中使用的MVC實現,並映象了基於Servlet的spring-webmvc模組的功能。
Message
Spring框架4包括spring-messaging從關鍵抽象模組 Spring整合專案,例如Message,MessageChannel,MessageHandler,和其他人作為基於訊息的應用奠定了基礎。該模組還包括一組用於將訊息對映到方法的註釋,類似於基於Spring MVC註釋的程式設計模型。
AOP
AOP模組提供了一個符合AOP聯盟標準的面向切面程式設計的實現,它讓你可以定義例如方法攔截器和切點,從而將邏輯程式碼分開,降低它們之間的耦合性,利用source-level的元資料功能,還可以將各種行為資訊合併到你的程式碼中。
單獨的spring-aspects模組提供與AspectJ的整合。
該spring-instrument模組提供了在某些應用程式伺服器中使用的類檢測支援和類載入器實現。該spring-instrument-tomcat 模組包含Spring的Tomcat檢測代理。
Test
該spring-test模組支援使用JUnit或TestNG對Spring元件進行單元測試和整合測試。
Spring 依賴
GroupId |
ArtifactId |
org.springframework |
spring-aop |
org.springframework |
spring-aspects |
org.springframework |
spring-beans |
org.springframework |
spring-context |
org.springframework |
spring-context-support |
org.springframework |
spring-core |
org.springframework |
spring-expression |
org.springframework |
spring-instrument |
org.springframework |
spring-instrument-tomcat |
org.springframework |
spring-jdbc |
org.springframework |
spring-jms |
org.springframework |
spring-messaging |
org.springframework |
spring-orm |
org.springframework |
spring-oxm |
org.springframework |
spring-test |
org.springframework |
spring-tx |
org.springframework |
spring-web |
org.springframework |
spring-webmvc |
org.springframework |
spring-webmvc-portlet |
org.springframework |
spring-websocket |
- 設計思想
- 通過容器裝配所用的BEAN
- 通過工廠模板建立bean
- 通過DI完成依賴注入
- 類圖設計
1、xml容器初始化過程
2、註解容器載入過程
- ComponentScanBeanDefinitionParser.parse 解析註解
- 核心分析
1、ApplicationContext與BeanFactory ioc探究
例項化的工作會在容器啟動後過AbstractApplicationContext中reflash方法自動進行。我們常用的ApplicationContext實現類ClassPathXmlApplicationContext繼承了AbstractApplicationContext類,繼承關係如下圖.
AbstractApplicationContext裡的reflash方法是Spring初始IOC容器一個非常重要的方法,不管你是ApplicationContext哪個實現類,最終都會進入這個方法。
IOC實現
ApplicationContext 容器
ClassPathXmlApplicationContext
FileSystemXmlApplicationContext
AbstractApplicationContext
//ioc核心程式碼 初始化Bean視窗過程
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
// 呼叫容器準備重新整理的方法,獲取容器的當時時間,同時給容器設定同步標識
this.prepareRefresh();
/告訴子類啟動refreshBeanFactory()方法,Bean定義資原始檔的載入從 //子類的refreshBeanFactory()方法啟動
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
//為容器的某些子類指定特殊的BeanPost事件處理器
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);
//為BeanFactory註冊BeanPost事件處理器.
//BeanPostProcessor是Bean後置處理器,用於監聽容器觸發的事件
this.registerBeanPostProcessors(beanFactory);
//初始化資訊源,和國際化相關.
this.initMessageSource();
//初始化容器事件傳播器.
this.initApplicationEventMulticaster();
//呼叫子類的某些特殊Bean初始化方法
this.onRefresh();
//為事件傳播器註冊事件監聽器.
this.registerListeners();
//初始化所有剩餘的單態Bean.
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
if(this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
//銷燬以建立的單態Bean
this.destroyBeans();
//取消refresh操作,重置容器的同步標識.
this.cancelRefresh(var9);
throw var9;
} finally {
//清空快取
this.resetCommonCaches();
}
}
}
//重新整理bean工廠
protected final void refreshBeanFactory() throws BeansException {
if(this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
this.customizeBeanFactory(beanFactory);
this.loadBeanDefinitions(beanFactory);
Object var2 = this.beanFactoryMonitor;
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}
loadBeanDefinitions 載入BeanDefinition
AOP核心分析
1、Jdk動態代理實現
- 手寫實現
- 手寫spring ioc di 容器與依賴注入
- 目錄結構
- bean介面
package com.ofsoft.framework.core;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.core.ResolvableType;
/**
* @author OF
* @version v1.0
* @className BenaFaction
* @date 2018/9/27
*/
public interface OFBeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String var1);
<T> T getBean(String var1, Class<T> var2) ;
<T> T getBean(Class<T> var1) throws IllegalAccessException, InstantiationException;
Class<?> getType(String var1);
}
- 具體實現
package com.ofsoft.framework.core;
import com.ofsoft.framework.annotation.OFAutowired;
import com.ofsoft.framework.stereotype.OFComponent;
import com.ofsoft.framework.stereotype.OFRepository;
import com.ofsoft.framework.stereotype.OFService;
import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author OF
* @version v1.0
* @className OFApplicationContext
* @date 2018/9/27
*/
public class OFApplicationContext implements OFBeanFactory {
private static Map<String, Object> iocMapping = new ConcurrentHashMap<String, Object>();
public OFApplicationContext(String basePackage) {
init(basePackage);
}
/**
* 初始化
*
* @param basePackage
*/
private void init(String basePackage) {
//初始化配置檔案
//載入IOC容器
initBean(basePackage);
//di依賴注入
inject();
}
private void initBean(String basePackage) {
//獲取所用檔案
List<String> files = findClassScanner(basePackage);
for (String fileName : files) {
Class<?> clazz = getClass(fileName);
//別名
String alis = getClassForAlis(clazz);
if (alis != null) {
Object obj = newInstance(clazz);
if ("".equals(alis)) {
iocMapping.put(firstToLowerCase(clazz.getSimpleName()), obj);
//根據介面型別例項
Class[] interfaces = clazz.getInterfaces();
for (Class anInterface : interfaces) {
iocMapping.put(firstToLowerCase(anInterface.getSimpleName()), obj);
}
} else {
//根據別名
iocMapping.put(alis, obj);
}
}
}
}
private String firstToLowerCase(String str) {
char[] c = str.toCharArray();
c[0] += 32;
return String.valueOf(c);
}
private Class<?> getClass(String classPath) {
try {
return Class.forName(classPath);
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
private Object newInstance(Class clazz) {
try {
return clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
/**
*
*/
public String getClassForAlis(Class<?> clazz) {
if (clazz.isAnnotationPresent(OFRepository.class) && !clazz.isAssignableFrom(OFRepository.class)) {
OFRepository repository = clazz.getAnnotation(OFRepository.class);
return repository.value();
} else if (clazz.isAnnotationPresent(OFService.class) && !clazz.isAssignableFrom(OFService.class)) {
OFService service = clazz.getAnnotation(OFService.class);
return service.value();
} else if (clazz.isAnnotationPresent(OFComponent.class) && !clazz.isAssignableFrom(OFComponent.class) && !clazz.isAssignableFrom(OFRepository.class) && !clazz.isAssignableFrom(OFService.class)) {
OFComponent component = clazz.getAnnotation(OFComponent.class);
return component.value();
} else {
return null;
}
}
private List<String> findClassScanner(final String basePackage) {
File file = new File(this.getClass().getClassLoader().getResource(basePackage.replaceAll("\\.", "/")).getFile());
final List<String> classFiles = new ArrayList<String>();
file.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
if (file.isDirectory()) {
classFiles.addAll(findClassScanner(basePackage + "." + file.getName()));
} else {
if (file.getName().endsWith(".class")) {
classFiles.add(basePackage + "." + file.getName().replace(".class", ""));
return true;
}
}
return false;
}
});
return classFiles;
}
@Override
public Object getBean(String beanName) {
return iocMapping.get(beanName);
}
@Override
public <T> T getBean(String beanName, Class<T> type) {
return type.cast(getBean(beanName));
}
@Override
public <T> T getBean(Class<T> type) {
try {
return type.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
@Override
public Class<?> getType(String beanName) {
return getBean(beanName).getClass();
}
private void inject() {
try {
for (Map.Entry<String, Object> entry : iocMapping.entrySet()) {
String clazz = entry.getKey();
Object obj = entry.getValue();
//獲取所用欄位
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(OFAutowired.class)) {
//設定訪問許可權
field.setAccessible(true);
OFAutowired autowired = field.getAnnotation(OFAutowired.class);
if (!"".equals(autowired.value())) {
//根據別名
Object object = iocMapping.get(autowired.value());
field.set(obj, object);
} else {
//根據型別
Class<?> fieldClazz = field.getType();
Iterator iter = iocMapping.values().iterator();
while (iter.hasNext()) {
Object object = iter.next();
if (fieldClazz.isAssignableFrom(object.getClass())) {
field.set(obj, object);
break;
}
}
}
}
}
}
} catch (IllegalAccessException e1) {
e1.printStackTrace();
}
}
}
- 測試
package com.ofsoft.demo;
import com.ofsoft.demo.bean.TestBean;
import com.ofsoft.framework.core.OFApplicationContext;
import com.ofsoft.demo.service.UserService;
/**
* @author OF
* @version v1.0
* @className App
* @date 2018/9/27
*/
public class App {
public static void main(String[] args) {
OFApplicationContext applicationContext = new OFApplicationContext("com.ofsoft");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.showUser();
TestBean testBean = applicationContext.getBean("testBean", TestBean.class);
testBean.show();
}
}
- 手寫AOP
//代理物件需要的實現的介面
//利用spring的API,建立介面代理工廠
ProxyFactory proxy = new ProxyFactory();
proxy.setTarget(new Animal());
proxy.addAdvice(new MethodBeforeAdvice() {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("在吃飯方法呼叫之前攔截:吃飯前要洗手");
}
});
proxy.addAdvice(new AfterReturningAdvice() {
@Override
public void afterReturning(Object boj,Method method, Object[] objects, Object o) throws Throwable {
System.out.println("吃飯方法完成之後呼叫:飯後要洗碗");
}
});
Animal animalProxy = (Animal) proxy.getProxy();
animalProxy.eat();
- 總結(設計模式)
- 策略
- 模板
- 工廠
- 代理
- 介面隔離
- 依賴倒置
- 開閉原則
- 單一原則
類方法:判斷類型別是否相同。
isAssignableFrom