<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      spring詳解-IOC

      Spring--IOC容器

      Spring 是一個基于 Java 平臺的開源全棧應用程序框架,也是一個控制反轉(IoC)容器實現。

      Spring IoC 容器即 Spring 框架中負責管理“Bean”(由容器實例化、配置并組裝的普通 POJO 對象)的核心組件。容器讀取配置元數據(XML、注解或 Java 配置類),解析 Bean 定義,然后在啟動或按需時實例化 Bean,完成依賴注入,并負責 Bean 的整個生命周期管理。

      本文章示例代碼見該倉庫:【spring】中的“spring”模塊。

      倉庫地址:https://gitee.com/quercus-sp204/sourcecode-and-demos

      1.相關概念

      IOC: Inversion of control 【控制反轉】

      控制反轉是一種設計原則,其核心思想是:將程序中對象的創建、配置和生命周期管理的控制權,從應用代碼“反轉”交給外部框架或容器來負責。在傳統的程序設計中,業務邏輯代碼主動調用庫或框架完成通用功能;而在 IoC 中,則是框架或容器主動調用開發者編寫的代碼,實現“控制權”反轉,此外呢,IoC 不是一種技術,而是一種思想。

      降低組件間的耦合度,提升系統的可維護性和擴展性。例如,傳統開發中Service層直接依賴Dao層的具體實現,而IoC通過容器動態注入依賴,使兩者解耦。

      DI:Dependency Injection 【依賴注入】

      依賴注入是 IoC 最常見的一種實現方式。在 DI 模式下,對象只需聲明它所依賴的其他對象(通過構造器、屬性或工廠方法),由 IoC 容器在實例化時自動“注入”這些依賴,從而實現組件間的松耦合和可測試性提升。

      在Spring中,我們可以通過構造器注入、Setter方法注入或字段注入(如@Autowired)。

      // 構造器注入
      @Component
      public class UserService {
          private final UserDao userDao;
          @Autowired
          public UserService(UserDao userDao) {
              this.userDao = userDao;
          }
      }
      

      2.核心類介紹

      我們都知道,spring可以從xml配置文件中解析bean的定義,同時也可以結合相關注解(例如@Configuration, @Bean等)來定義相關bean。最經典的就是這兩種了,下面我們就基于這兩種類型,來介紹一下相關的核心類。

      ①基本的

      • Bean工廠相關接口以及context

      上面的類間關系圖我們需要了解的是紅色框框中的三個,BeanFactory、ApplicationEventPublisher、ApplicationContext

      BeanFactory : IOC容器的核心接口,定義了基礎功能(如getBean()containsBean()),可以看到,BeanFactory是一個頂級接口,定義了比較常用的getBean方法。

      public interface BeanFactory {
          String FACTORY_BEAN_PREFIX = "&";
          Object getBean(String name) throws BeansException;
          <T> T getBean(String name, Class<T> requiredType) throws BeansException;
          <T> T getBean(Class<T> requiredType) throws BeansException;
          boolean containsBean(String name);
          .....
      }
      

      ApplicationContextBeanFactory的擴展接口,提供高級功能(如國際化、事件發布、AOP支持)

      用于為應用程序提供配置的中央接口。這在應用程序運行時是只讀的,但如果實現支持,則可以重新加載。ApplicationContext提供:

      繼承自 ListableBeanFactory用于訪問應用程序組件的 Bean 工廠方法。

      繼承自ResourceLoader 接口用以通用方式加載文件資源的能力。

      繼承自 ApplicationEventPublisher 接口能夠將事件發布到已注冊的偵聽器。

      繼承自 MessageSource 接口 能夠解析消息的能力,支持國際化。

      public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
      		MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
          .....
      }
      

      ApplicationEventPublisher:封裝事件發布功能的接口。

      @FunctionalInterface
      public interface ApplicationEventPublisher {
          /*
          向在此應用程序注冊過應用程序事件的匹配偵聽器 發送通知。
          事件可以是框架事件(例如 ContextRefreshedEvent)或特定于應用程序的事件。
          這樣的事件發布步驟實際上是移交給 multicaster,并不意味著同步異步執行,甚至根本不意味著立即執行。
          建議事件偵聽器盡可能高效,單獨使用異步執行來執行運行時間較長且可能阻塞的作。
          */
      	default void publishEvent(ApplicationEvent event) {
      		publishEvent((Object) event);
      	}
          void publishEvent(Object event); // 接口
      }
      

      spring各種類非常多,所以在上圖中,我這里只做出了各自類之間的大致關系。

      DefaultListableBeanFactory: Spring IoC 容器的 基礎實現類,直接管理 Bean 的全生命周期(實例化、依賴注入、銷毀);通過BeanDefinitionRegistry 接口注冊/移除 Bean 定義(如 XML 或注解配置);preInstantiateSingletons() 方法來實例化bean。-----這個方法是實現了接口ConfigurableListableBeanFactory

      AbstractApplicationContext:是 容器啟動的模板,擴展了企業級功能并依賴 BeanFactory 實現業務邏輯,通過 refresh() 方法定義容器啟動流程(如加載配置、注冊 BeanFactoryPostProcessor)。在其子類實現中,重寫了obtainFreshBeanFactory()方法,可以獲取到beanFactory

      • Bean定義

      BeanDefinition 接口用于描述一個 Bean 實例的元信息,包括類名、構造函數參數、屬性值、作用域、初始化/銷毀方法等。

      public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
          .....
      }
      

      BeanDefinitionHolder 封裝一個 BeanDefinition 以及它對應的 Bean 名稱和別名,可用于內部 Bean 的占位或編程式注冊時攜帶額外信息。

      public class BeanDefinitionHolder implements BeanMetadataElement {
      
      	private final BeanDefinition beanDefinition;
      
      	private final String beanName;
      
      	@Nullable
      	private final String[] aliases;
          ....
      }
      

      BeanDefinitionBuilder 用于以流式 API 構造 GenericBeanDefinitionRootBeanDefinitionChildBeanDefinition 等,并設置各種屬性(如 scopelazyInitautowireModeinitMethod 等)。

      ②基于注解的context

      AnnotationConfigApplicationContext :是 Spring 注解驅動配置的核心實現。其中的關鍵組件:

      • AnnotatedBeanDefinitionReader
        負責解析配置類(@Configuration)并注冊 Bean 定義。

        核心邏輯

        • 通過 registerBean() 方法將配置類轉換為 AnnotatedGenericBeanDefinition
        • 處理 @Bean 方法,生成對應的 Bean 定義。
        • 注冊 BeanPostProcessor(如 ConfigurationClassPostProcessor)。
      • ClassPathBeanDefinitionScanner
        掃描包路徑下的類,注冊組件(@Component@Service)。

        • 過濾條件:默認掃描帶有 @Component 及其派生注解的類。
        • 擴展點:可通過 includeFiltersexcludeFilters 自定義過濾規則。

      該context初始化流程

      1. 構造階段
        • 創建 DefaultListableBeanFactory(底層 BeanFactory)。
        • 初始化 AnnotatedBeanDefinitionReaderClassPathBeanDefinitionScanner
      2. 注冊階段
        • 解析配置類,生成 BeanDefinition(如 AnnotatedGenericBeanDefinition)。
        • 將 Bean 定義注冊到 BeanDefinitionRegistry(即 DefaultListableBeanFactory)。
      3. 刷新階段refresh()):
        • 準備環境:驗證配置屬性。
        • 獲取 BeanFactory:確保 DefaultListableBeanFactory 已初始化。
        • 注冊 BeanPostProcessor:如 AutowiredAnnotationBeanPostProcessor
        • 完成 Bean 實例化:通過 preInstantiateSingletons() 預加載單例 Bean。

      ③基于配置文件的context

      ClassPathXmlApplicationContext :

      • 基于 XML 配置的 Spring 容器:通過加載類路徑(ClassPath)下的 XML 文件初始化 Spring 容器,管理 Bean 的生命周期和依賴注入。
      • ApplicationContext 的實現類:繼承自 AbstractApplicationContext,提供完整的容器功能(如國際化、事件機制)。
      • 傳統 Spring 應用的核心入口:適用于 XML 配置驅動的項目(如早期 Spring 項目)。

      示例:

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
          <bean scope="singleton" class="com.feng.xmlobj.Policeman" name="policeman">
              <constructor-arg name="name" value="國窖001"/>
          </bean>
      </beans>
      
      public class XmlContextMain {
          public static void main(String[] args) {
              ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("all-spring.xml");
              Policeman policeman = context.getBean(Policeman.class);
              policeman.say();
          }
      }
      
      // 實體類
      public class Policeman {
          private String name;
          public Policeman(){
              System.out.println("Policeman 構造函數");
          }
          public Policeman(String name){
              this.name = name;
          }
          public void say() {
              System.out.println(this.name + "報道!");
          }
      }
      

      該示例見spring模塊中的帶有xml前綴的類和包。

      現在ClassPathXmlApplicationContext用的很少了,現代 Spring 開發更傾向注解配置。

      3. 容器創建

      在了解到了基本的類,以及他們之間的大致關系之后,這本節我們來探索一下IOC容器是如何創建的。那我們就以注解配置的context為例子。

      ApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
      Husband h = context.getBean(Husband.class);
      h.say();
      

      從構造函數一步一步向下走

      // AnnotationConfigApplicationContext.java
      public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
          this(); // 1.無參構造
          register(componentClasses); // 2.注冊配置類并生成BeanDefinition
          refresh(); // 3.容器刷新
      }
      

      ①構造函數

      // 1.無參構造
      public AnnotationConfigApplicationContext() {
          StartupStep createAnnotatedBeanDefReader = getApplicationStartup().start("spring.context.annotated-bean-reader.create");
          // 初始化注解 Bean 定義讀取器,通過讀取器預注冊這些處理器,
          // 以確保后續注解解析和依賴注入的基礎能力。
          /*
          創建 AnnotatedBeanDefinitionReader 實例,負責將 
          注解配置類(如 @Configuration、@Component)轉換為 BeanDefinition
          自動注冊關鍵組件:
          ConfigurationClassPostProcessor(解析 @Configuration 類)。
          AutowiredAnnotationBeanPostProcessor(處理 @Autowired)。
          CommonAnnotationBeanPostProcessor(處理 @Resource、@PostConstruct)。
          EventListenerMethodProcessor(處理 @EventListener)。
          */
          this.reader = new AnnotatedBeanDefinitionReader(this);
          createAnnotatedBeanDefReader.end();
          /*
          創建 ClassPathBeanDefinitionScanner 實例,負責掃描類路徑下的組件類(如 @Component、@Service)
          */
          this.scanner = new ClassPathBeanDefinitionScanner(this);
      }
      

      在創建AnnotatedBeanDefinitionReader的時候,默認會創建幾個BeanDefinition放到beanDefinitionMap里面。

      ②注冊配置類

      // 2.注冊配置類并生成BeanDefinition
      @Override
      public void register(Class<?>... componentClasses) {
          Assert.notEmpty(componentClasses, "At least one component class must be specified");
          StartupStep registerComponentClass = getApplicationStartup().start("spring.context.component-classes.register")
                  .tag("classes", () -> Arrays.toString(componentClasses));
          this.reader.register(componentClasses);
          registerComponentClass.end();
      }
      
      // AnnotatedBeanDefinitionReader.java
      public void register(Class<?>... componentClasses) {
          for (Class<?> componentClass : componentClasses) {
              registerBean(componentClass);
          }
      }
      
      // 往下最后是調用下面這個
      private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
              @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
              @Nullable BeanDefinitionCustomizer[] customizers) {
          // 1.看見沒,把Main類封裝成了一個BeanDefinition
          AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
          if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
              return;
          }
          // 2.這里就相當于在設置BeanDefinition的屬性
          abd.setInstanceSupplier(supplier);
          ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
          abd.setScope(scopeMetadata.getScopeName());
          String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
          AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
          ....
      	// 3.注冊Bean定義
          BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
          definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
          // 通過 BeanDefinitionReaderUtils 將 BeanDefinitionHolder 
          // 注冊到 BeanFactory 的 beanDefinitionMap 中
          BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
      }
      
      // BeanDefinitionReaderUtils.java
      public static void registerBeanDefinition(
              BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
              throws BeanDefinitionStoreException {
          String beanName = definitionHolder.getBeanName();
          // =========這里
          registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
          String[] aliases = definitionHolder.getAliases();
          if (aliases != null) {
              for (String alias : aliases) {
                  registry.registerAlias(beanName, alias);
              }
          }
      }
      
      // GenericApplicationContext.java
      @Override
      public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
              throws BeanDefinitionStoreException {
          this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
      }
      
      // DefaultListableBeanFactory.java
      @Override
      public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
              throws BeanDefinitionStoreException {
          .....
          // 1.從緩存beanDefinitionMap中查
          BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
          if (existingDefinition != null) {
              if (!isAllowBeanDefinitionOverriding()) {
                  throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
              }
              else if (existingDefinition.getRole() < beanDefinition.getRole()) {
                  // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
                  ....
              }
              else if (!beanDefinition.equals(existingDefinition)) {
                  ....
              }
              else {
                  .....
              }
              this.beanDefinitionMap.put(beanName, beanDefinition);
          }
          else { // 2.緩存中沒有
              // hasBeanCreationStarted()方法是用來檢查此工廠的 bean 創建階段是否已經開始,
              // 即在此期間是否有任何 bean 被標記為已創建。此時肯定是沒有任何bean創建了的
              if (hasBeanCreationStarted()) {
                  synchronized (this.beanDefinitionMap) {
                      this.beanDefinitionMap.put(beanName, beanDefinition);
                      List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                      updatedDefinitions.addAll(this.beanDefinitionNames);
                      updatedDefinitions.add(beanName);
                      this.beanDefinitionNames = updatedDefinitions;
                      removeManualSingletonName(beanName);
                  }
              }
              else {
                  // 放到beanDefinitionMap里面
                  this.beanDefinitionMap.put(beanName, beanDefinition);
                  this.beanDefinitionNames.add(beanName);
                  removeManualSingletonName(beanName);
              }
              this.frozenBeanDefinitionNames = null;
          }
      	...
      }
      

      這一步把主配置類封裝成了一個beanDefinition放進了beanDefinitionMap里面。

      ③容器刷新【最核心】

      refresh()方法是AbstractApplicationContext里面重寫的ConfigurableApplicationContext接口的方法。

      @Override
      public void refresh() throws BeansException, IllegalStateException {
          synchronized (this.startupShutdownMonitor) {
              StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
              // 1. 準備上下文刷新
              prepareRefresh();
              // 2. 獲取beanFactory
              ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
              // 3. 準備beanFactory,添加一些組件
              prepareBeanFactory(beanFactory);
              try {
                 // 4. 子類擴展設置beanFactory
                  postProcessBeanFactory(beanFactory);
                  StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
                  // 5. 執行 BeanFactoryPostProcessor 方法
                  invokeBeanFactoryPostProcessors(beanFactory);
                  // 6. 注冊 BeanPostProcessors
                  registerBeanPostProcessors(beanFactory);
                  beanPostProcess.end();
                  // 7. 初始化 MessageSource 組件,比如做國際化
                  initMessageSource();
                  // 8. 初始化事件派發器,在注冊監聽器時會用到
                  initApplicationEventMulticaster();
                  // 9.【模板方法】子類重寫這個方法,在容器刷新的時候可以自定義邏輯-
                  // 例如Servlet的容器,里面會啟動嵌入的tomcat
                  onRefresh();
                  //10.注冊監聽器
                  registerListeners();
                  // 11. 創建所有的bean,并且初始化 【最核心的一個方法】
                  finishBeanFactoryInitialization(beanFactory);
                  // 12.容器刷新完成,發布一個事件
                  finishRefresh();
              }
              catch (BeansException ex) {
                  // 出現異常的步驟-這里就不看了
              }
              finally {
                  
                  resetCommonCaches();
                  contextRefresh.end();
              }
          }
      }
      

      可以看到,這個方法巨長,里面調用了十幾個方法。加個鎖確保安全性,就沒啥好解釋的了。。。上面有十幾個步驟,其中一些不是很重要的我這里就不去分析了,僅做一個簡要介紹

      準備上下文刷新

      刷新前的預處理,設置容器狀態并初始化環境。設置 active=true(容器激活)、closed=false

      初始化環境變量(Environment),校驗必填屬性(如數據庫 URL)

      protected void prepareRefresh() {
          // Switch to active.
          this.startupDate = System.currentTimeMillis();
          this.closed.set(false);
          this.active.set(true);
      	..
          // Initialize any placeholder property sources in the context environment.
          initPropertySources();
          // Validate that all properties marked as required are resolvable:
          // see ConfigurablePropertyResolver#setRequiredProperties
          getEnvironment().validateRequiredProperties();
          ....
      }
      

      獲取beanFactory

      protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
          refreshBeanFactory();
          return getBeanFactory();
      }
      

      返回的是DefaultListableBeanFactory類型的bean工廠

      準備beanFactory

      BeanFactory 添加通用組件和配置;設置類加載器(ClassLoader);注冊 BeanPostProcessor(如 ApplicationContextAwareProcessor);忽略特定接口的自動裝配(如 ServletContextAware)。

      protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
      		...
      		beanFactory.setBeanClassLoader(getClassLoader());
      		...
      		// 注冊BeanPostProcessor
      		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
      		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
      		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
      		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
      		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
      		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
      		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
      		beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
      		// Register early post-processor for detecting inner beans as ApplicationListeners.
      		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
      		..
      	}
      

      子類擴展設置beanFactory

      子類擴展點,用于對 BeanFactory 進行后置處理。比如說,Web 環境中注冊 ServletContext 作用域;動態注冊自定義的 BeanDefinition

      執行 BeanFactoryPostProcessor 方法

      ? 執行 BeanFactoryPostProcessor,修改 BeanDefinition,也就是說可以用 BeanFactoryPostProcessor 來定制配置的元數據。這個接口的語義與 BeanPostProcessor 相似,但有一個主要區別: BeanFactoryPostProcessor 在 Bean 配置元數據上運行。也就是說,Spring IoC 容器允許 BeanFactoryPostProcessor 在容器實例化任何 Bean(BeanFactoryPostProcessor 實例除外)之前讀取配置元數據并進行可能的更改。在這里我們只先知道BeanPostProcessorBeanFactoryPostProcessor這兩個接口就行了,在后面做具體分析。

      ? 通過查閱spring官方文檔得知: 我們可以配置多個 BeanFactoryPostProcessor 實例,并可通過設置 order 屬性來控制這些 BeanFactoryPostProcessor 實例的運行順序。但是,只有當 BeanFactoryPostProcessor 實現了 Ordered 接口時,才能設置該屬性。

      ? invokeBeanFactoryPostProcessors里面大致可以分為兩部分:

      1. 處理BeanDefinitionRegistryPostProcessor:優先處理BeanDefinitionRegistryPostProcessor,允許動態注冊Bean定義(如@Configuration類解析)。例如ConfigurationClassPostProcessor,這個就會解析加了@Configuration的配置類,還會解析@ComponentScan、@ComponentScans注解掃描的包,以及解析@Import等注解。
      
      2. 處理BeanFactoryPostProcessor:處理BeanFactoryPostProcessor,僅修改現有Bean定義(如PropertySourcesPlaceholderConfigurer解析占位符)
      
      // AbstractApplicationContext.java
      //在Bean實例化之前執行,確保所有'Bean定義'已被后置處理器處理完畢
      invokeBeanFactoryPostProcessors(beanFactory);
      
      protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
          //委托給PostProcessorRegistrationDelegate執行所有后置處理器
          // getBeanFactoryPostProcessors()返回上下文配置中顯式注冊的BeanFactoryPostProcessor
          PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
      
          // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
          // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
          if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null &&
                  beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
              beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
              beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
          }
      }
      
      // PostProcessorRegistrationDelegate.java
      // 這個方法巨長無比
      public static void invokeBeanFactoryPostProcessors(
      	ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
          
          // invokeBeanDefinitionRegistryPostProcessors部分
          // 解析容器中其他的BeanDefinition,放到eanDefinitionMap里面
          // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
          invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
          
          // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
          invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
          ..... 
          // 最后一部分
          // 執行普通BeanFactoryPostProcessor
          // 實現了PriorityOrdered的
          // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
          sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
          invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); //=====
          // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
          // 實現了Ordered的
          List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
          for (String postProcessorName : orderedPostProcessorNames) {
              orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
          }
          sortPostProcessors(orderedPostProcessors, beanFactory);
          invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); //=====
          // 最普通的
          // Finally, invoke all other BeanFactoryPostProcessors.
          List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
          for (String postProcessorName : nonOrderedPostProcessorNames) {
              nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
          }
          invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); //=====
      
          // Clear cached merged bean definitions since the post-processors might have
          // modified the original metadata, e.g. replacing placeholders in values...
          beanFactory.clearMetadataCache();
      }
      
      private static void invokeBeanFactoryPostProcessors(
              Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
      
          for (BeanFactoryPostProcessor postProcessor : postProcessors) {
              StartupStep postProcessBeanFactory = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process").tag("postProcessor", postProcessor::toString);
              postProcessor.postProcessBeanFactory(beanFactory); // 調用方法
              postProcessBeanFactory.end();
          }
      }
      

      如下示例使用:

      @Configuration
      public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
          @Override
          public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
              BeanDefinition husband = beanFactory.getBeanDefinition("husband");
              System.out.println(husband);
          }
      }
      

      注冊 BeanPostProcessors

      registerBeanPostProcessors 方法的主要功能是注冊所有的 BeanPostProcessor 類型的 bean。

      protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
          PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
      }
      

      實際邏輯由 PostProcessorRegistrationDelegate 類的靜態方法 registerBeanPostProcessors 處理, 將容器中所有 BeanPostProcessor 實例注冊到 BeanFactory,以便后續 Bean 初始化時調用。

      BeanFactoryPostProcessor,也分先后順序:

      ? 1.PriorityOrdered:最高優先級(如 BeanValidationPostProcessor)。

      ? 2.Ordered:次高優先級(通過 @Order 注解或實現 Ordered 接口)。

      ? 3.普通:無順序要求。

      初始化 MessageSource 組件

      用于初始化國際化(i18n)相關的消息源(MessageSource

      初始化事件派發器

      initApplicationEventMulticaster()

      主要作用是初始化應用程序事件多播器ApplicationEventMulticaster)。事件多播器的功能是把應用程序事件(ApplicationEvent)廣播給所有注冊的事件監聽器(ApplicationListener)。

      舉個例子:【見倉庫中的 event 包】

      public class HelloEvent extends ApplicationEvent { // 定義一個事件
          private String message;
          public HelloEvent(Object source, String message) { // 第一個參數必須是source
              super(source);
              this.message = message;
          }
          public String getMessage() {
              return message;
          }
      }
      // 事件發布
      @Component(value = "helloEventPublisher")
      public class HelloEventPublisher {
          @Autowired
          private ApplicationEventPublisher publisher;
      
          public void publishEvent(String msg) {
              HelloEvent event = new HelloEvent(this, msg);
              publisher.publishEvent(event);
          }
      }
      // 監聽器1
      // 基于注解(支持異步+條件)
      @Component
      public class HelloEventListener {
          // 需要開啟異步支持
          // @Async
          // @EventListener
          public void handleEvent(HelloEvent helloEvent) {
              System.out.println("【(異步方式)事件監聽到了:】" + helloEvent.getMessage());
              try {
                  Thread.sleep(1000);
                  System.out.println("【(異步方式)事件監聽結束了】");
              } catch (InterruptedException e) {
                  throw new RuntimeException(e);
              }
          }
          // 條件監聽(僅處理特定用戶)
          @EventListener(condition = "#event.message.endsWith('-VIP')")
          public void vipNotification(HelloEvent event) {
              System.out.println("VIP事件 " + event.getMessage() );
          }
      }
      // 監聽器2
      //基于接口(同步監聽)
      // @Component
      public class InterfaceHelloEventListener implements ApplicationListener<HelloEvent> {
          @Override
          public void onApplicationEvent(HelloEvent event) {
              System.out.println("【基于接口的方式-listener】" + event.getMessage());
          }
      }
      

      那么,如下場景我們可以考慮用事件發布監聽的方式來實現。

      1. 電商系統
        • 用戶下單 → 發布 OrderCreatedEvent
        • 監聽器:庫存扣減、優惠券核銷、支付回調
      2. 社交平臺
        • 用戶發帖 → 發布 PostCreatedEvent
        • 監聽器:內容審核、推薦算法觸發、消息推送
      3. 微服務架構
        • 服務A完成操作 → 發布領域事件
        • 服務B通過消息隊列中間件訂閱事件實現最終一致性

      自定義邏輯

      onRefresh();【模板方法的設計模式】

      舉個例子:比如說我們的SpringBoot應用,假如開啟了web支持,在其子類中,會重寫該方法。

      // ServletWebServerApplicationContext.java
      @Override
      protected void onRefresh() {
          super.onRefresh();
          try {
              createWebServer(); // 創建內嵌Tomcat容器
          }
          catch (Throwable ex) {
              throw new ApplicationContextException("Unable to start web server", ex);
          }
      }
      

      注冊監聽器

      將監聽器注冊到事件廣播器(ApplicationEventMulticaster)中,并觸發早期事件的廣播。

      protected void registerListeners() {
          // 注冊靜態監聽器
          // 1.getApplicationListeners返回在 Spring 容器初始化前通過編程方式手動注冊的監聽器
          //(例如在配置類中直接添加的監聽器)。
          for (ApplicationListener<?> listener : getApplicationListeners()) {
              getApplicationEventMulticaster().addApplicationListener(listener);
          }
      
          // 2. 注冊 Bean 定義的監聽器
          // 獲取所有實現了 ApplicationListener 接口的 Bean 名稱(不實例化 Bean,僅獲取名稱)
          String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
          for (String listenerBeanName : listenerBeanNames) {
              // 通過 Bean 名稱注冊監聽器,延遲到事件觸發時才獲取 Bean 實例
              getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
          }
      
          // Publish early application events now that we finally have a multicaster...
          // 3.發布早期事件
          Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
          this.earlyApplicationEvents = null;
          if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
              for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                  getApplicationEventMulticaster().multicastEvent(earlyEvent);
              }
          }
      }
      

      實例所有的bean **【important】

      // Instantiate all remaining (non-lazy-init) singletons.
      finishBeanFactoryInitialization(beanFactory);
      

      最核心的步驟了,我們順著這個方法,一直往下,可以發現到達了這里。

      // AbstractApplicationContext.java
      // Instantiate all remaining (non-lazy-init) singletons.
      beanFactory.preInstantiateSingletons();
      
      // 實際上是DefaultListableBeanFactory.java 是 BeanFactory的子類實現
      @Override
      public void preInstantiateSingletons() throws BeansException {
          List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
          //實例化非延遲單例Bean
          for (String beanName : beanNames) {
              RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
              if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                  // 處理FactoryBean和非FactoryBean
                  if (isFactoryBean(beanName)) { // 工廠Bean特殊處理
                      Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                      .....
                  }
                  // 觸發普通Bean的實例化與初始化【重點關注的是這個】
                  else {
                      /*
                      getBean()會觸發Bean的實例化、依賴注入、@PostConstruct方法、
                      InitializingBean.afterPropertiesSet()等初始化邏輯
                      */
                      getBean(beanName);
                  }
              }
          }
      
          for (String beanName : beanNames) {
              Object singletonInstance = getSingleton(beanName);
              // 觸發SmartInitializingSingleton回調
              if (singletonInstance instanceof SmartInitializingSingleton) {
                  StartupStep smartInitialize = getApplicationStartup().start("spring.beans.smart-initialize")
                          .tag("beanName", beanName);
                  SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                  ...
                  smartSingleton.afterSingletonsInstantiated();
                  ...
                  smartInitialize.end();
              }
          }
      }
      

      也就是說上面的方法可以分為兩個部分: 1.實例化所有非Lazy的bean;2.觸發SmartInitializingSingleton回調,也就是說,SmartInitializingSingleton接口的afterSingletonsInstantiated()方法在所有單例Bean實例化完成后執行。

      SmartInitializingSingleton階段,我們可以做什么呢?舉個簡單的例子:緩存預熱嘛,是吧

      @Component
      public class CacheWarmupBean implements SmartInitializingSingleton {
          @Autowired
          private CacheManager cacheManager;
      
          @Override
          public void afterSingletonsInstantiated() {
              cacheManager.getCache("userCache").putAll(loadInitialData());
          }
      }
      

      那么,我們重點關注第一個部分中的普通bean的實例化和初始化getBean(beanName)

      // AbstractBeanFactory.java
      @Override
      public Object getBean(String name) throws BeansException {
          return doGetBean(name, null, null, false);
      }
      protected <T> T doGetBean(
          String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
          throws BeansException {
          // 這個里面只給出關鍵部分
          // 1.檢查單例緩存
          /*
          此步驟會先從單例 Bean 緩存中查找指定名稱的 Bean 實例。
          Spring 使用三級緩存機制來管理單例 Bean,這里會嘗試從一級緩存(singletonObjects)、
          二級緩存(earlySingletonObjects)和
          三級緩存(singletonFactories)中獲取 Bean 實例
          */
          // Eagerly check singleton cache for manually registered singletons.
      	Object sharedInstance = getSingleton(beanName);
          ...
              
          //3.保證當前 Bean 所依賴的 bean 的初始化。
          String[] dependsOn = mbd.getDependsOn();
          if (dependsOn != null) {
      		.....
          }
          
          //4.Create bean instance.
          //4.1 創建單例bean【重點】
          if (mbd.isSingleton()) {
              sharedInstance = getSingleton(beanName, () -> {
                  try {
                      return createBean(beanName, mbd, args);
                  }
                  ....
              });
              beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
          }
          //4.2 創建原型bean
          //4.3 其他
      }
      

      可以看到上面的方法大致分為了4步,

      首先檢查緩存getSingleton(beanName)本質往下面是調用了DefaultSingletonBeanRegistry的protected Object getSingleton(String beanName, boolean allowEarlyReference) 方法。

      第二步,合并 Bean 定義:解析父類或父容器的 Bean 定義(支持繼承) ---- 這個不是很重要,問的gpt:合并Bean定義的核心目的是實現配置的繼承與復用,通過將父Bean的公共配置與子Bean的個性化配置結合,提高代碼的可維護性和靈活性】

      第三步,檢查依賴關系【@DependsOn注解】,若 Bean 有依賴的其他 Bean,會先遞歸獲取這些依賴的 Bean 實例,同時檢查是否存在循環依賴。

      最后一步就是創建bean了,這里只關注單例bean的創建,調用了重載的方法public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory),第二個參數是一個函數式接口,即對象工廠,里面的getObject()方法就是調用的lambda表達式里面的邏輯如下。

      () -> {
          try {
              return createBean(beanName, mbd, args);
          }....
      }
      

      搞清楚了這層關系,那我們就來看重載的getSingleton方法

      // DefaultSingletonBeanRegistry.java
      public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
          ...
          synchronized (this.singletonObjects) {
              Object singletonObject = this.singletonObjects.get(beanName);
              if (singletonObject == null) {
                  ...
                  beforeSingletonCreation(beanName);
                  boolean newSingleton = false;
                  boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                  if (recordSuppressedExceptions) {
                      this.suppressedExceptions = new LinkedHashSet<>();
                  }
                  try {
                      // 這一步是調用的上面lambda表達式的createBean(beanName, mbd, args);
                      singletonObject = singletonFactory.getObject(); 
                      newSingleton = true;
                  }
                  catch (IllegalStateException ex) {
                      .....
                  }
                  catch (BeanCreationException ex) {
                      .....
                  }
                  finally {
                      if (recordSuppressedExceptions) {
                          this.suppressedExceptions = null;
                      }
                      afterSingletonCreation(beanName);
                  }
                  if (newSingleton) {
                      // 放入單例池,刪除二三級緩存
                      addSingleton(beanName, singletonObject);
                  }
              }
              return singletonObject;
          }
      }
      
      // lambda表達式的createBean(beanName, mbd, args);
      // AbstractAutowireCapableBeanFactory.java
      @Override
      protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
              throws BeanCreationException {
      
          .....
          try {
              Object beanInstance = doCreateBean(beanName, mbdToUse, args);
              ......
              return beanInstance;
          }
          ....
      }
      
      protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
              throws BeanCreationException {
          // 1. 實例化bean
          BeanWrapper instanceWrapper = null;
          if (mbd.isSingleton()) {
              instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
          }
          if (instanceWrapper == null) {
              instanceWrapper = createBeanInstance(beanName, mbd, args);
          }
          Object bean = instanceWrapper.getWrappedInstance();
          Class<?> beanType = instanceWrapper.getWrappedClass();
          if (beanType != NullBean.class) {
              mbd.resolvedTargetType = beanType;
          }
          // Allow post-processors to modify the merged bean definition.
          ....
          // 緩存早期單例,以便能夠解析循環引用
          boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                  isSingletonCurrentlyInCreation(beanName));
          if (earlySingletonExposure) {
              if (logger.isTraceEnabled()) {
                  ...
              }
              addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
          }
          // 初始化bean
          Object exposedObject = bean;
          try {
              // 依賴注入:屬性填充
              populateBean(beanName, mbd, instanceWrapper);
              // 執行初始化方法
              exposedObject = initializeBean(beanName, exposedObject, mbd);
          }
          catch (Throwable ex) {
              ...
          }
          /*
          是在 Bean 創建完成后,檢查并處理該 Bean 的早期單例引用。
          如果存在早期單例引用,會根據具體情況對最終暴露的 Bean 對象進行調整,
          以確保在循環依賴的場景下,依賴該 Bean 的其他 Bean 使用的是正確版本的 Bean 實例。
          就是確保最終所有依賴都指向完全初始化的Bean
          */
          if (earlySingletonExposure) {
              Object earlySingletonReference = getSingleton(beanName, false);
              if (earlySingletonReference != null) {
                  if (exposedObject == bean) {
                      exposedObject = earlySingletonReference;
                  }
                  else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                      String[] dependentBeans = getDependentBeans(beanName);
                      Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                      for (String dependentBean : dependentBeans) {
                          if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                              actualDependentBeans.add(dependentBean);
                          }
                      }
                      ..
                  }
              }
          }
          // Register bean as disposable.
          try {
              registerDisposableBeanIfNecessary(beanName, bean, mbd);
          }
          catch (BeanDefinitionValidationException ex) {
              ...
          }
          return exposedObject;
      }
      

      了解了上面的代碼結構,我們可以理清楚如下思路。

      從上圖我們可以看出,bean的創建和初始化等操作,都是在createBean中完成的。

      populateBean(beanName, mbd, instanceWrapper):屬性填充

      populateBean 是 Spring 框架中用于填充 Bean 屬性的核心方法,負責將 Bean 定義中的屬性值(如依賴注入、配置值等)注入到 Bean 實例中。它是 Bean 生命周期中實例化后、初始化前的關鍵步驟,屬于 AbstractAutowireCapableBeanFactory 類的一部分,屬性注入完成后,才會執行 @PostConstructInitializingBean.afterPropertiesSet()

      @Autowired@Resource 注解的解析是在調用 InstantiationAwareBeanPostProcessorpostProcessProperties 方法時完成的。具體來說,Spring 提供了 AutowiredAnnotationBeanPostProcessor 來處理 @Autowired 注解,CommonAnnotationBeanPostProcessor 來處理 @Resource 注解。

      當執行到 InstantiationAwareBeanPostProcessorpostProcessProperties 方法時,AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor 會掃描 Bean 類的字段、方法和構造函數,查找帶有 @Autowired@Resource 注解的元素,然后根據注解的配置進行依賴注入。

      // 屬性填充大致可以劃分為兩部分
      //1.postProcessAfterInstantiation
      //這里會遍歷所有實現了 InstantiationAwareBeanPostProcessor 接口的后置處理器,調用它們的 postProcessAfterInstantiation 方法
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
          for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
              if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                  return;
              }
          }
      }
      //2.postProcessProperties【@Autowired 和 @Resource 解析】 && postProcessPropertyValues
      //再次遍歷所有實現了 InstantiationAwareBeanPostProcessor 接口的后置處理器,調用它們的 postProcessProperties 方法。
      //若該方法返回 null,則進一步調用 postProcessPropertyValues 方法。
      for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
          PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
          if (pvsToUse == null) {
              ....
              pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
              ...
          }
          pvs = pvsToUse;
      }
      

      initializeBean(beanName, exposedObject, mbd) : bean初始化

      initializeBean 是 Spring 框架中 Bean 生命周期管理的核心方法,負責執行 Bean 的初始化階段。它在 Bean 實例化、屬性填充后觸發,確保 Bean 完成最終的配置和初始化邏輯。

      protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
          ...
          // 1.處理 Aware 接口回調
       	invokeAwareMethods(beanName, bean);
          Object wrappedBean = bean;
          if (mbd == null || !mbd.isSynthetic()) {
              // 2.應用 BeanPostProcessor 的前置處理方法
              wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
          }
          try {
              // 3. 調用 Bean 的初始化方法
              invokeInitMethods(beanName, wrappedBean, mbd);
          }
          catch (Throwable ex) {
              throw new BeanCreationException(
                      (mbd != null ? mbd.getResourceDescription() : null),
                      beanName, "Invocation of init method failed", ex);
          }
          if (mbd == null || !mbd.isSynthetic()) {
              // 4.應用 BeanPostProcessor 的后置處理方法【可能會生成代理對象】
              wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
          }
          return wrappedBean;
      }
      

      可以看到bean初始化有大致四個步驟:

      1. 如果 Bean 實現了 BeanNameAwareBeanFactoryAware 等 Aware 接口,調用對應方法

      2. 遍歷所有 BeanPostProcessor,調用 postProcessBeforeInitialization

      3. 調用 Bean 的初始化方法:@PostConstruct 注解的方法InitializingBean.afterPropertiesSet()XML 配置的 init-method

      4. 對初始化后的 Bean 進一步處理(如生成 AOP 代理

      在調試的時候,我們發現在applyBeanPostProcessorsAfterInitialization()方法中出現了如下所示:

      執行了AnnotationAwareAspectJAutoProxyCreator類 :: postProcessAfterInitialization() 方法。 它是 Spring AOP 的核心組件之一,負責根據注解(如 @Aspect@Before)動態生成 AOP 代理。也就是說,Spring IOC 容器創建 bean 實例時,最后都會對 bean 進行處理,來實現增強。對于 Spring AOP 來說,就是創建代理類。 【見后續文章 SpringAOP】

      容器刷新完成

      protected void finishRefresh() {
          // 清除上下文級資源緩存(例如掃描中的 ASM 元數據)-- 不了解
          clearResourceCaches();
          // 為此上下文初始化生命周期處理器。
          initLifecycleProcessor();
      
          // Propagate refresh to lifecycle processor first.
          getLifecycleProcessor().onRefresh();
      
          // 發布一個ContextRefreshedEvent事件 -- 
          // 這個可以了解一下【上面也介紹到了事件event】
          publishEvent(new ContextRefreshedEvent(this));
      
          // Participate in LiveBeansView MBean, if active.
          if (!NativeDetector.inNativeImage()) {
              LiveBeansView.registerApplicationContext(this);
          }
      }
      

      負責完成應用上下文刷新的最后階段,

      end.參考

      1. https://blog.csdn.net/xiaofeng10330111/article/details/85253251 【csdn--張彥峰ZYF--理解IOC與DI】
      2. https://blog.csdn.net/ivan820819/article/details/79744797 【csdn--ivan820819--淺談IOC--說清楚IOC是什么】
      3. https://segmentfault.com/a/1190000038438265最簡 Spring AOP 源碼分析!
      posted @ 2025-04-16 20:13  別來無恙?  閱讀(453)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 无码人妻一区二区三区在线视频 | 狠狠色综合久久丁香婷婷| 欧美日韩国产综合草草| 人人澡人摸人人添| 亚洲欧美人成网站在线观看看| 国产一区二区不卡在线| 日韩有码中文字幕国产| 国产av一区二区午夜福利| av区无码字幕中文色| 天堂网av成人在线观看| 天天摸天天做天天爽水多| 欧洲码亚洲码的区别入口| 无码国产一区二区三区四区| 亚洲欧美综合精品成人网站| 好吊妞人成视频在线观看27du| 精品尤物TV福利院在线网站| 亚洲国产精品久久久久婷婷图片| 中文精品无码中文字幕无码专区| 国产一区二区av天堂热| 国产极品粉嫩学生一线天| 日本欧美大码a在线观看| 98日韩精品人妻一二区| 亚洲精品乱码久久久久久按摩高清| 国产一区二区三区麻豆视频| 乱人伦中文视频在线| 激情综合色综合啪啪开心| 欧美一区二区三区在线观看| 在线观看中文字幕码国产| 福利无遮挡喷水高潮| 中文字幕一区二区三区麻豆| 久久精品国产只有精品96| 中文字幕久区久久中文字幕| 免费无码av片在线观看播放| 文中字幕一区二区三区视频播放 | 一区二区三区四区五区自拍| 1精品啪国产在线观看免费牛牛| 国产麻豆精品手机在线观看| 国产永久免费高清在线观看| 伊人久久久大香线蕉综合直播| 亚洲av无码牛牛影视在线二区 | 国产精品熟女亚洲av麻豆|