Spring 由七大模塊組成,分別是


數據訪問與集成模塊,分為以下小模塊:
JDBC(Java Database Connectivity),Java數據庫連接ORM(Object Relational Mapping),?對象關系映射OXM(Object XML Mapping),?對象XML映射JMS(Java Message Service),Java消息服務Transactions,事務Web有以下小模塊:
Web 模塊:提供了核心部分,如 編解碼,過濾器,序列化,國際化,跨域,轉換器,客戶端和服務端等。
WebMVC 模塊:即我們平時用的?SpringMVC
WebSocket 模塊:?用來支持這個?全雙工通信
WebFlux模塊:?就是這個響應式Web編程模塊
4.7.1.1.3 切面模塊包括AOP、Aspect兩個模塊。
AOP:基于代理的 Aop 框架
Aspect:定義了五種類型的切面
Instrumentation , 這個是 Java 的一個接口,用于
Spring-messaging模塊提供了一種基于?WebSocket的?STOMP協議實現STOMP(Simple Text Oriented Messaging Protocol) 是一種?流文本定向消息協議,也是一種為MOM(Message Oriented Middleware,面向消息的中間件)設計的簡單文本協議
常見的這幾個MQ都支持該協議,比如?RocketMQ,RabbitMQ,ActiveMQ。
待更新
Spring的這七大模塊你了解嗎? - 知乎
4.7.1.1.6 核心模塊分為四個核心模塊:
該核心模塊為重點,
4.7.1.1.7 測試模塊主要是測試用,如Junit等。

我們可以將bean概念態、定義態、純靜態、成熟態
概念態:
定義態:bean的構造圖
純靜態:循環依賴中體現純靜態的作用
成熟態:最終在應用中使用的bean
其中在ApplicationContext()中隱藏了另外兩種狀態

BeanDefinition是相當重要的?
BeanDefinition:封裝了bean的定義信息,決定一個bean是怎么生產的,一個bean對應一個BeanDefinition

那么這個BeanDefinition是怎么來的呢?

當我們new ApplicationContext時會傳入一個xml文件。不同的sapring上下文會傳入不同的,讀取bean定義的過程是有些不同的,但也有相同的地方。
方式一:ClassPathXmlApplicationContext(xml);
方式二:AnnotationConfigApplicationContext(配置類);無論是ClassPathXmlApplicationContext(xml)還是AnnotationConfigApplicationContext(配置類)都有一個統一的接口ApplicationContext,因此它們會將公共的部分抽取出來,我們來研究這些公共的部分。
雖然有不同的spring上下文,但是都是由BeanDefinitionReader接口讀取配置信息
讀取之后怎么解析注解呢?
用掃描器ClassPathBeanDefinitionScanner,比如,我們定義了
![]()
它會掃描包下的.class,里面有component注解,將這個類注冊為BeanDefinition。由于每個類都會有BenaDefinition,所以用beanDefinitionMap容器保存。
![]()
之后由registerBeanDefinition將BeanDefinition注冊到BeanDefinitionMap中

之后就是生產bean了。
4.7.2.3 生產bean這里涉及到很重要的知識點:BeanFactory接口
BeanFactory負責生產,在BeanFactory中提供了getBean方法用來生產bean。

提出一個小問題,這里Spring容器調用的getBean和BeanFactory里的getBean是同一個方法嗎?

答案:是同一個
我們進入applicationContext.getBean(),會發現這里的getBean是門面方法,沒有具體,而是交給BeanFactory去生產。

當已存在bean就直接返回給spring,如果沒有就生產后返回。

既然ApplicationContext和BeanFactory都可以獲取bean,也就是說二者均可作為容器去使用。

那么既然都可以作為容器,為什么不直接在spring中書寫BeanFactroy,非要再整個ApplicationContext的門面方法,不多此一舉么?
看完上面的繼承圖,我們發現ApplicationContext實現了BeanFactroy,這就好比,我們要買車,我們可以選擇去4S店,也可以選擇直接去汽車工廠。ApplicationContext就好比4S店,4S店有很多的服務,我們只需要提需求,4S店都能完成。BeanFactroy就是汽車工廠,工廠的職責就一個:生產汽車?;旧衔覀兒?S店比較熟悉,打交道比較多,同樣我們開發人員和ApplicationContext打交道比較多。我們只需要把配置給ApplicationContext,它就能初始化。
但是BeanFactroy不行,它只實現了簡單工廠,功能單一化,只能根據BeanDefinition去生產bean。
通過ApplicationContext,我們只需要getBean(car),就可以得到我們想要的bean,但是,如果注釋了ApplicationContext,我們再直接用beanFactory.get(car),就會報錯BeanDefinitionException。

因為像xml、配置類的信息,都是由ApplicationContext(Spring 上下文)幫我們做了,ApplicationContext調用了BeanFactory來生產bean。

但是對于BeanFactory,我們必須手動將BenaDefinition傳給BeanFactory,才能生產bean。
但是BeanFactory內存更小,可以用于嵌入式開發。
4.7.2.4 實例化bean實例化bean的方式:
@Component
將類讀取到beanClass中,spring利用反射實例化bean
4.7.2.4.2 工廠方法注解形式
public class StaticFactoryBean {
?@Bean
? public static UserService createUserService(){ ? ?
????????? return new UserServiceImpl();
? }
}
會將被標注的方法讀取到factoryMethodName
xml形式
而
在factory-method=" "中指定一個工廠方法,且這個工廠方法是靜態的,會將方法讀取到factoryMethodName?
4.7.2.4.3 工廠類注意FactoryBean本身也是一個bean
類實例化FactoryBean接口,并重寫getObject()、getObjectType()
@Component
public class FactoryBean_test implements FactoryBean {
@Override
public Object getObject() throws Exception {
//這個才是返回的真正的bean
return new User();
}
@Override
public Class>getObjectType() {
return User.class;
}
工廠方法基于方法,而工廠類基于類
4.7.2.5?屬性注入 4.7.2.5.1 循環依賴
屬性注入之后,進行初始化,初始化時會調用init_Method()

除了init-Method()外
還可以用注解@PostConstruct聲明一個初始化方法
以及利用InitializingBean接口,實現一個InitializingBean,重寫afterPropertiesSet()
4.7.2.6.2 aware擴展接口檢查aware接口設置相關依賴
在spring容器中,我們可以把對象按照使用者分為兩類:自定義對象、容器使用的對象
但是如果我們自定義對象需要使用、調用這些容器所使用的對象時,怎么辦?
你可以把這些容器所使用的對象當成一個普通屬性,如果是屬性,我肯定要調用屬性的set方法,往里面賦值。但是,對象的創建都交由容器來管理了,set方法調用肯定還是由容器管理,而且容器又不知道什么時候調用。
所以這里設置了統一的入口——aware接口。
所有調用容器對象設置的地方都會實現aware接口,如BeanFactoryAware、BeanNameAware等。
總的來說就是通過aware的具體實現子類,我們可以設置bean的一系列操作。
4.7.2.7 創建Bean
創建好的bean會放入Map(單例池/一級緩存)中
當context.getBean("bean的名字");時,會到一級緩存中查詢,有就返回,沒有就生產。
4.7.2.8 擴展接口 4.7.2.8.1 BeanFactoryPostProcessor接口@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory BeanFactory) throws BeansException;
}BeanFactoryPostProcessor中的postProcessBeanFactory()方法,直接傳來一個
4.7.2.8.2 BeanDefinitionRegistryPostProcessor源碼定義如下:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}BeanDefinitionRegistryPostProcessor的作用是注冊BeanDefinition,也就是注冊了Bean
Spring-MyBatis中的Mapper是接口,動態代理

BeanPostProcessor(bean的后置處理器)主要用在初始化前后
BeanPostProcessor有很多子接口
4.7.3 Bean生命周期 4.7.3.1 簡化版本1、實例化bean,當客戶向容器請求一個尚未初始化的bean時,容器就會調用doCreateBean()方法進行實例化,實際上就是利用反射來創建一個bean對象
2、當bean對象創建出來后就對bean對象進行屬性填充,也就是注入這個bean依賴的其他對象
3、屬性填充完成后,進行初始化bean操作
a、執行Aware接口方法,Spring會檢查該bean對象是否實現了xxxAware接口,通過Aware類型的接口,我們可以拿到spring容器的一些資源,如實現了BeanNameAware接口就可以獲取BeanName等等
b、執行BeanPostProcessor的前置處理方法postProcessBeforeInitialization(),對Bean進行一些自定義的前置處理
c、判斷bean是否實現了InitialalizationBean接口,如果實現了,將會執行InitialalizationBean的afterPropertiesSet()初始化方法
d、執行用戶自定義的初始化方法,如init-method等
e、執行BeanPostProcessor的后置處理方法postProcessAfterInitialization()
4、銷毀
a、首先判斷Bean是否實現了DestructionAwareBeanPostProcessor接口,如果實現了,則執行DestructionAwareBeanPostProcessor后置處理器的銷毀方法
b、其次判斷Bean是否實現了DisposableBean接口,如果實現了就會調用其實現的destroy()方法
c、最后判斷Bean是否配置了destroy-method方法,如果有就調用其配置的銷毀方法

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
//bean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
//如果緩存中不存在,則調用createBeanInstance創建一個BeanWrapper(bean的包裝類)
if (instanceWrapper == null) {
//bean的實例化
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
//初始化bean實例
Object exposedObject = bean;
//----------------省略-----------
//屬性填充
this.populateBean(beanName, mbd, instanceWrapper);
//初始化bean,如執行aware接口的子類,執行init-method方法,BeanPostProcesso后置增強等
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
//銷毀不在AbstractAutowireCapableBeanFactory 類,在DisposableBeanAdapter類中
}initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() ->{
//先執行aware的子類
this.invokeAwareMethods(beanName, bean);
return null;
}, this.getAccessControlContext());
} else {
this.invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//執行beanPostProcessor后置處理器的前置方法BeanPostProcessorsBeforeInitialization
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
//中間執行init-method
try {
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
//最后執行BeanPostProcessorsAfterInitialization
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
invokeAwareMethods
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
//如果bean實現了BeanNameAware,那bean內部可以獲取到beanName屬性
if (bean instanceof BeanNameAware) {
((BeanNameAware)bean).setBeanName(beanName);
}
//其他同理
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = this.getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware)bean).setBeanFactory(this);
}
}
}invokeInitMethods
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
//InitialalizationBean接口,如果實現了,將會執行InitialalizationBean的afterPropertiesSet()初始化方法
boolean isInitializingBean = bean instanceof InitializingBean;
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
//執行afterPropertiesSet()
AccessController.doPrivileged(() ->{
((InitializingBean)bean).afterPropertiesSet();
return null;
}, this.getAccessControlContext());
} catch (PrivilegedActionException var6) {
throw var6.getException();
}
} else {
((InitializingBean)bean).afterPropertiesSet();
}
}
//用戶自定義的初始化方法
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
//用戶自定義的方法
this.invokeCustomInitMethod(beanName, bean, mbd);
}
}
}DisposableBeanAdapter
//銷毀
class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
Iterator var1 = this.beanPostProcessors.iterator();
while(var1.hasNext()) {
//先查看DestructionAwareBeanPostProcessor接口
DestructionAwareBeanPostProcessor processor = (DestructionAwareBeanPostProcessor)var1.next();
//如果實現了,則執行DestructionAwareBeanPostProcessor后置處理器的銷毀方法
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
//接著看是否實現了DisposableBean接口
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() ->{
//如果實現了就調用接口的destroy方法
((DisposableBean)this.bean).destroy();
}
}
//最后判斷是否有用戶自定義的銷毀方法
if (this.destroyMethod != null) {
this.invokeCustomDestroyMethod(this.destroyMethod);
} else if (this.destroyMethodName != null) {
Method methodToInvoke = this.determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
//調用用戶自定義的銷毀方法
this.invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}Spring的理解
Spring是什么?
框架:方便開發,整合其他框架
容器:管理bean
生態:目前主流的Java開發,都會用到Java全家桶。Springboot、Springcloud等框架都是對Spring的擴展實現。
11張流程圖搞定 Spring Bean 生命周期 - 知乎
4.7.3.3 循環依賴 4.7.3.3.1 循環依賴問題
singletonObject(一級緩存):存放實例化 ->代理 ->屬性注入 ->初始化后的對象
earlySingletonObjects(二級緩存):存放實例化 ->代理 ->屬性注入 ->初始化后的對象
4.7.3.3.3 流程singletonFactories(三級緩存):存放對象工廠,可以從對象工廠中拿到還未屬性注入的對象(對象工廠便于創建代理對象)
當getBean(),獲取bean時,spring會先到一級緩存中找,沒有再去二級緩存,若二級緩存還沒有就會創建一個對應的工廠對象
4.7.4 AOP單例bean
Spring中的Bean對象默認是單例的,框架并沒有對Bean進行多線程封裝處理
單例bean是指IOC容器中就只有這么一個bean,是全局共享的。分為有狀態bean和無狀態bean。
有狀態的bean
就是有實例變量的對象,可以保存數據(有狀態就是有數據存儲功能),是線程不安全的。每個用戶都有自己特有的實例,在用戶的生命周期中,bean保存了用戶的信息,即為“偶狀態”;一旦用戶衰亡(調用結束),bean的生命周期也隨之結束。即每個用戶最初都會得到一個初始的bean。
無狀態的bean
就是沒有實例變量的對象,不能保存數據,是不變類,是線程安全的。bean一旦實例化就被加進會話池中,各個用戶都可以共用。即使用戶已經消亡,bean的生命期也不一定結束,它可能依然存在于會話池中,供其他用戶調用。由于沒有特定的用戶,那么也就不能保持某一用戶的狀態,所以叫無狀態bean。但無狀態會話bean 并非沒有狀態,如果它有自己的屬性(變量),那么這些變量就會受到所有調用它的用戶的影響,這是在實際應用中必須注意的。
實例變量
java類的成員變量有倆種:一種是被static關鍵字修飾的變量,叫類變量或者靜態變量;另一種沒有static修飾,為實例變量。
如
class Car{
private name;? ?//這就是實例變量
public void 方法(){};
}
當一個對象被實例化之后,每個實例變量的值就跟著確定;
實例變量在對象創建的時候創建,在對象被銷毀的時候銷毀;
如果Bean是有狀態的,那就需要開發人員自己來進行線程安全的保證,最簡單的辦法就是改變bean的作用域 把 "singleton"改為’‘protopyte’ 這樣每次請求Bean就相當于是 new Bean() 這樣就可以保證線程的安全了。
無狀態就是不會存儲數據,試想controller,service和dao本身并不是線程安全的,只是調用里面的方法,而且多線程調用一個實例的方法,會在內存中復制遍歷,這是自己線程的工作內存,是最安全的。因此在進行使用的時候,不要在bean中聲明任何有狀態的實例變量或者類變量,如果必須如此,也推薦大家使用ThreadLocal把變量變成線程私有,如果bean的實例變量或者類變量需要在多個線程之間共享,那么就只能使用synchronized、lock、cas等這些實現線程同步的方法。但是一旦使用了synchronized、lock等線程同步方法,又會降低系統效率。
你是否還在尋找穩定的海外服務器提供商?創新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統配攻擊溯源,準確流量調度確保服務器高可用性,企業級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧
網頁題目:4.7深入理解Spring-創新互聯
地址分享:http://www.yijiale78.com/article16/doccgg.html
成都網站建設公司_創新互聯,為您提供App設計、網站制作、品牌網站建設、定制開發、外貿網站建設、營銷型網站建設
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯