源碼分析---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;
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;
public class OFApplicationContext implements OFBeanFactory {
private static Map<String, Object> iocMapping = new ConcurrentHashMap<String, Object>();
public OFApplicationContext(String basePackage) {
init(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;
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