日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

【死磕 Spring】—– IOC 之 Factory 实例化 bean

發(fā)布時(shí)間:2025/3/20 javascript 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【死磕 Spring】—– IOC 之 Factory 实例化 bean 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
這篇我們關(guān)注創(chuàng)建 bean 過(guò)程中的第一個(gè)步驟:實(shí)例化 bean,對(duì)應(yīng)的方法為: createBeanInstance(),如下:
  • protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {

  • // 解析 bean,將 bean 類名解析為 class 引用

  • Class<?> beanClass = resolveBeanClass(mbd, beanName);


  • if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {

  • throw new BeanCreationException(mbd.getResourceDescription(), beanName,

  • "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());

  • }


  • // 如果存在 Supplier 回調(diào),則使用給定的回調(diào)方法初始化策略

  • Supplier<?> instanceSupplier = mbd.getInstanceSupplier();

  • if (instanceSupplier != null) {

  • return obtainFromSupplier(instanceSupplier, beanName);

  • }


  • // 如果工廠方法不為空,則使用工廠方法初始化策略

  • if (mbd.getFactoryMethodName() != null) {

  • return instantiateUsingFactoryMethod(beanName, mbd, args);

  • }


  • boolean resolved = false;

  • boolean autowireNecessary = false;

  • if (args == null) {

  • // constructorArgumentLock 構(gòu)造函數(shù)的常用鎖

  • synchronized (mbd.constructorArgumentLock) {

  • // 如果已緩存的解析的構(gòu)造函數(shù)或者工廠方法不為空,則可以利用構(gòu)造函數(shù)解析

  • // 因?yàn)樾枰鶕?jù)參數(shù)確認(rèn)到底使用哪個(gè)構(gòu)造函數(shù),該過(guò)程比較消耗性能,所有采用緩存機(jī)制

  • if (mbd.resolvedConstructorOrFactoryMethod != null) {

  • resolved = true;

  • autowireNecessary = mbd.constructorArgumentsResolved;

  • }

  • }

  • }

  • // 已經(jīng)解析好了,直接注入即可

  • if (resolved) {

  • // 自動(dòng)注入,調(diào)用構(gòu)造函數(shù)自動(dòng)注入

  • if (autowireNecessary) {

  • return autowireConstructor(beanName, mbd, null, null);

  • }

  • else {

  • // 使用默認(rèn)構(gòu)造函數(shù)構(gòu)造

  • return instantiateBean(beanName, mbd);

  • }

  • }


  • // 確定解析的構(gòu)造函數(shù)

  • // 主要是檢查已經(jīng)注冊(cè)的 SmartInstantiationAwareBeanPostProcessor

  • Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);

  • if (ctors != null ||

  • mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||

  • mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {

  • // 構(gòu)造函數(shù)自動(dòng)注入

  • return autowireConstructor(beanName, mbd, ctors, args);

  • }


  • //使用默認(rèn)構(gòu)造函數(shù)注入

  • return instantiateBean(beanName, mbd);

  • }

  • 實(shí)例化 bean 是一個(gè)復(fù)雜的過(guò)程,其主要的邏輯為:

    如果存在 Supplier 回調(diào),則調(diào)用 obtainFromSupplier() 進(jìn)行初始化

    如果存在工廠方法,則使用工廠方法進(jìn)行初始化

    首先判斷緩存,如果緩存中存在,即已經(jīng)解析過(guò)了,則直接使用已經(jīng)解析了的,根據(jù) constructorArgumentsResolved 參數(shù)來(lái)判斷是使用構(gòu)造函數(shù)自動(dòng)注入還是默認(rèn)構(gòu)造函數(shù)

    如果緩存中沒(méi)有,則需要先確定到底使用哪個(gè)構(gòu)造函數(shù)來(lái)完成解析工作,因?yàn)橐粋€(gè)類有多個(gè)構(gòu)造函數(shù),每個(gè)構(gòu)造函數(shù)都有不同的構(gòu)造參數(shù),所以需要根據(jù)參數(shù)來(lái)鎖定構(gòu)造函數(shù)并完成初始化,如果存在參數(shù)則使用相應(yīng)的帶有參數(shù)的構(gòu)造函數(shù),否則使用默認(rèn)構(gòu)造函數(shù)。

    下面就上面四種情況做分別說(shuō)明。

    obtainFromSupplier()

  • Supplier<?> instanceSupplier = mbd.getInstanceSupplier();

  • if (instanceSupplier != null) {

  • return obtainFromSupplier(instanceSupplier, beanName);

  • }

  • 首先從 BeanDefinition 中獲取 Supplier,如果不為空,則調(diào)用 obtainFromSupplier() 。那么 Supplier 是什么呢?在這之前也沒(méi)有提到過(guò)這個(gè)字段。

  • public interface Supplier<T> {

  • T get();

  • }

  • Supplier 接口僅有一個(gè)功能性的 get(),該方法會(huì)返回一個(gè) T 類型的對(duì)象,有點(diǎn)兒類似工廠方法。這個(gè)接口有什么作用?用于指定創(chuàng)建 bean 的回調(diào),如果我們?cè)O(shè)置了這樣的回調(diào),那么其他的構(gòu)造器或者工廠方法都會(huì)沒(méi)有用。在什么設(shè)置該參數(shù)呢?Spring 提供了相應(yīng)的 setter 方法,如下:

  • public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {

  • this.instanceSupplier = instanceSupplier;

  • }

  • 在構(gòu)造 BeanDefinition 的時(shí)候設(shè)置了該值,如下(以 RootBeanDefinition 為例):

  • public <T> RootBeanDefinition(@Nullable Class<T> beanClass, String scope, @Nullable Supplier<T> instanceSupplier) {

  • super();

  • setBeanClass(beanClass);

  • setScope(scope);

  • setInstanceSupplier(instanceSupplier);

  • }

  • 如果設(shè)置了 instanceSupplier 則調(diào)用 obtainFromSupplier() 完成 bean 的初始化,如下:

  • protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {

  • String outerBean = this.currentlyCreatedBean.get();

  • this.currentlyCreatedBean.set(beanName);

  • Object instance;

  • try {

  • // 調(diào)用 Supplier 的 get(),返回一個(gè)對(duì)象

  • instance = instanceSupplier.get();

  • }

  • finally {

  • if (outerBean != null) {

  • this.currentlyCreatedBean.set(outerBean);

  • }

  • else {

  • this.currentlyCreatedBean.remove();

  • }

  • }

  • // 根據(jù)對(duì)象構(gòu)造 BeanWrapper 對(duì)象

  • BeanWrapper bw = new BeanWrapperImpl(instance);

  • // 初始化 BeanWrapper

  • initBeanWrapper(bw);

  • return bw;

  • }

  • 代碼很簡(jiǎn)單,調(diào)用 調(diào)用 Supplier 的 get() 方法,獲得一個(gè) bean 實(shí)例對(duì)象,然后根據(jù)該實(shí)例對(duì)象構(gòu)造一個(gè) BeanWrapper 對(duì)象 bw,最后初始化該對(duì)象。有關(guān)于 BeanWrapper 后面專門(mén)出文講解。

    instantiateUsingFactoryMethod()

    如果存在工廠方法,則調(diào)用 instantiateUsingFactoryMethod() 完成 bean 的初始化工作(方法實(shí)現(xiàn)比較長(zhǎng),細(xì)節(jié)比較復(fù)雜,各位就硬著頭皮看吧)。

  • protected BeanWrapper instantiateUsingFactoryMethod(

  • String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {

  • return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);

  • }

  • 構(gòu)造一個(gè) ConstructorResolver 對(duì)象,然后調(diào)用其 instantiateUsingFactoryMethod() 方法。ConstructorResolver 是構(gòu)造方法或者工廠類初始化 bean 的委托類。

  • public BeanWrapper instantiateUsingFactoryMethod(

  • final String beanName, final RootBeanDefinition mbd, @Nullable final Object[] explicitArgs) {


  • // 構(gòu)造 BeanWrapperImpl 對(duì)象

  • BeanWrapperImpl bw = new BeanWrapperImpl();

  • // 初始化 BeanWrapperImpl

  • // 向BeanWrapper對(duì)象中添加 ConversionService 對(duì)象和屬性編輯器 PropertyEditor 對(duì)象

  • //

  • this.beanFactory.initBeanWrapper(bw);


  • Object factoryBean;

  • Class<?> factoryClass;

  • boolean isStatic;


  • // 工廠名不為空

  • String factoryBeanName = mbd.getFactoryBeanName();

  • if (factoryBeanName != null) {

  • if (factoryBeanName.equals(beanName)) {

  • throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,

  • "factory-bean reference points back to the same bean definition");

  • }

  • // 獲取工廠實(shí)例

  • factoryBean = this.beanFactory.getBean(factoryBeanName);

  • if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {

  • throw new ImplicitlyAppearedSingletonException();

  • }

  • factoryClass = factoryBean.getClass();

  • isStatic = false;

  • }

  • else {

  • // 工廠名為空,則其可能是一個(gè)靜態(tài)工廠


  • // 靜態(tài)工廠創(chuàng)建bean,必須要提供工廠的全類名

  • if (!mbd.hasBeanClass()) {

  • throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,

  • "bean definition declares neither a bean class nor a factory-bean reference");

  • }

  • factoryBean = null;

  • factoryClass = mbd.getBeanClass();

  • isStatic = true;

  • }


  • // 工廠方法

  • Method factoryMethodToUse = null;

  • ConstructorResolver.ArgumentsHolder argsHolderToUse = null;

  • // 參數(shù)

  • Object[] argsToUse = null;


  • // 工廠方法的參數(shù)

  • // 如果指定了構(gòu)造參數(shù)則直接使用

  • // 在調(diào)用 getBean 方法的時(shí)候指定了方法參數(shù)

  • if (explicitArgs != null) {

  • argsToUse = explicitArgs;

  • }

  • else {

  • // 沒(méi)有指定,則嘗試從配置文件中解析

  • Object[] argsToResolve = null;

  • // 首先嘗試從緩存中獲取

  • synchronized (mbd.constructorArgumentLock) {

  • // 獲取緩存中的構(gòu)造函數(shù)或者工廠方法

  • factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;

  • if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {

  • // 獲取緩存中的構(gòu)造參數(shù)

  • argsToUse = mbd.resolvedConstructorArguments;

  • if (argsToUse == null) {

  • // 獲取緩存中的構(gòu)造函數(shù)參數(shù)的包可見(jiàn)字段

  • argsToResolve = mbd.preparedConstructorArguments;

  • }

  • }

  • }

  • // 緩存中存在,則解析存儲(chǔ)在 BeanDefinition 中的參數(shù)

  • // 如給定方法的構(gòu)造函數(shù) A(int ,int ),則通過(guò)此方法后就會(huì)把配置文件中的("1","1")轉(zhuǎn)換為 (1,1)

  • // 緩存中的值可能是原始值也有可能是最終值

  • if (argsToResolve != null) {

  • argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);

  • }

  • }


  • //

  • if (factoryMethodToUse == null || argsToUse == null) {

  • // 獲取工廠方法的類全名稱

  • factoryClass = ClassUtils.getUserClass(factoryClass);


  • // 獲取所有待定方法

  • Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);

  • // 檢索所有方法,這里是對(duì)方法進(jìn)行過(guò)濾

  • List<Method> candidateSet = new ArrayList<>();

  • for (Method candidate : rawCandidates) {

  • // 如果有static 且為工廠方法,則添加到 candidateSet 中

  • if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {

  • candidateSet.add(candidate);

  • }

  • }


  • Method[] candidates = candidateSet.toArray(new Method[0]);

  • // 排序構(gòu)造函數(shù)

  • // public 構(gòu)造函數(shù)優(yōu)先參數(shù)數(shù)量降序,非public 構(gòu)造函數(shù)參數(shù)數(shù)量降序

  • AutowireUtils.sortFactoryMethods(candidates);


  • // 用于承載解析后的構(gòu)造函數(shù)參數(shù)的值

  • ConstructorArgumentValues resolvedValues = null;

  • boolean autowiring = (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);

  • int minTypeDiffWeight = Integer.MAX_VALUE;

  • Set<Method> ambiguousFactoryMethods = null;


  • int minNrOfArgs;

  • if (explicitArgs != null) {

  • minNrOfArgs = explicitArgs.length;

  • }

  • else {

  • // getBean() 沒(méi)有傳遞參數(shù),則需要解析保存在 BeanDefinition 構(gòu)造函數(shù)中指定的參數(shù)

  • if (mbd.hasConstructorArgumentValues()) {

  • // 構(gòu)造函數(shù)的參數(shù)

  • ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();

  • resolvedValues = new ConstructorArgumentValues();

  • // 解析構(gòu)造函數(shù)的參數(shù)

  • // 將該 bean 的構(gòu)造函數(shù)參數(shù)解析為 resolvedValues 對(duì)象,其中會(huì)涉及到其他 bean

  • minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);

  • }

  • else {

  • minNrOfArgs = 0;

  • }

  • }


  • LinkedList<UnsatisfiedDependencyException> causes = null;


  • for (Method candidate : candidates) {

  • // 方法體的參數(shù)

  • Class<?>[] paramTypes = candidate.getParameterTypes();


  • if (paramTypes.length >= minNrOfArgs) {

  • // 保存參數(shù)的對(duì)象

  • ArgumentsHolder argsHolder;


  • // getBean()傳遞了參數(shù)

  • if (explicitArgs != null){

  • // 顯示給定參數(shù),參數(shù)長(zhǎng)度必須完全匹配

  • if (paramTypes.length != explicitArgs.length) {

  • continue;

  • }

  • // 根據(jù)參數(shù)創(chuàng)建參數(shù)持有者

  • argsHolder = new ArgumentsHolder(explicitArgs);

  • }

  • else {

  • // 為提供參數(shù),解析構(gòu)造參數(shù)

  • try {

  • String[] paramNames = null;

  • // 獲取 ParameterNameDiscoverer 對(duì)象

  • // ParameterNameDiscoverer 是用于解析方法和構(gòu)造函數(shù)的參數(shù)名稱的接口,為參數(shù)名稱探測(cè)器

  • ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();

  • if (pnd != null) {

  • // 獲取指定構(gòu)造函數(shù)的參數(shù)名稱

  • paramNames = pnd.getParameterNames(candidate);

  • }



  • // 在已經(jīng)解析的構(gòu)造函數(shù)參數(shù)值的情況下,創(chuàng)建一個(gè)參數(shù)持有者對(duì)象

  • argsHolder = createArgumentArray(

  • beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);

  • }

  • catch (UnsatisfiedDependencyException ex) {

  • if (this.beanFactory.logger.isTraceEnabled()) {

  • this.beanFactory.logger.trace("Ignoring factory method [" + candidate +

  • "] of bean '" + beanName + "': " + ex);

  • }

  • if (causes == null) {

  • causes = new LinkedList<>();

  • }

  • causes.add(ex);

  • continue;

  • }

  • }


  • // isLenientConstructorResolution 判斷解析構(gòu)造函數(shù)的時(shí)候是否以寬松模式還是嚴(yán)格模式

  • // 嚴(yán)格模式:解析構(gòu)造函數(shù)時(shí),必須所有的都需要匹配,否則拋出異常

  • // 寬松模式:使用具有"最接近的模式"進(jìn)行匹配

  • // typeDiffWeight:類型差異權(quán)重

  • int typeDiffWeight = (mbd.isLenientConstructorResolution() ?

  • argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));

  • // 代表最接近的類型匹配,則選擇作為構(gòu)造函數(shù)

  • if (typeDiffWeight < minTypeDiffWeight) {

  • factoryMethodToUse = candidate;

  • argsHolderToUse = argsHolder;

  • argsToUse = argsHolder.arguments;

  • minTypeDiffWeight = typeDiffWeight;

  • ambiguousFactoryMethods = null;

  • }


  • // 如果具有相同參數(shù)數(shù)量的方法具有相同的類型差異權(quán)重,則收集此類型選項(xiàng)

  • // 但是,僅在非寬松構(gòu)造函數(shù)解析模式下執(zhí)行該檢查,并顯式忽略重寫(xiě)方法(具有相同的參數(shù)簽名)

  • else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&

  • !mbd.isLenientConstructorResolution() &&

  • paramTypes.length == factoryMethodToUse.getParameterCount() &&

  • !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {


  • // 查找到多個(gè)可匹配的方法

  • if (ambiguousFactoryMethods == null) {

  • ambiguousFactoryMethods = new LinkedHashSet<>();

  • ambiguousFactoryMethods.add(factoryMethodToUse);

  • }

  • ambiguousFactoryMethods.add(candidate);

  • }

  • }

  • }


  • // 沒(méi)有可執(zhí)行的工廠方法,拋出異常

  • if (factoryMethodToUse == null) {

  • if (causes != null) {

  • UnsatisfiedDependencyException ex = causes.removeLast();

  • for (Exception cause : causes) {

  • this.beanFactory.onSuppressedException(cause);

  • }

  • throw ex;

  • }

  • List<String> argTypes = new ArrayList<>(minNrOfArgs);

  • if (explicitArgs != null) {

  • for (Object arg : explicitArgs) {

  • argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");

  • }

  • }

  • else if (resolvedValues != null){

  • Set<ConstructorArgumentValues.ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());

  • valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());

  • valueHolders.addAll(resolvedValues.getGenericArgumentValues());

  • for (ConstructorArgumentValues.ValueHolder value : valueHolders) {

  • String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :

  • (value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));

  • argTypes.add(argType);

  • }

  • }

  • String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);

  • throw new BeanCreationException(mbd.getResourceDescription(), beanName,

  • "No matching factory method found: " +

  • (mbd.getFactoryBeanName() != null ?

  • "factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +

  • "factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +

  • "Check that a method with the specified name " +

  • (minNrOfArgs > 0 ? "and arguments " : "") +

  • "exists and that it is " +

  • (isStatic ? "static" : "non-static") + ".");

  • }

  • else if (void.class == factoryMethodToUse.getReturnType()) {

  • throw new BeanCreationException(mbd.getResourceDescription(), beanName,

  • "Invalid factory method '" + mbd.getFactoryMethodName() +

  • "': needs to have a non-void return type!");

  • }

  • else if (ambiguousFactoryMethods != null) {

  • throw new BeanCreationException(mbd.getResourceDescription(), beanName,

  • "Ambiguous factory method matches found in bean '" + beanName + "' " +

  • "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +

  • ambiguousFactoryMethods);

  • }


  • if (explicitArgs == null && argsHolderToUse != null) {

  • // 將解析的構(gòu)造函數(shù)加入緩存

  • argsHolderToUse.storeCache(mbd, factoryMethodToUse);

  • }

  • }


  • try {

  • // 實(shí)例化 bean

  • Object beanInstance;


  • if (System.getSecurityManager() != null) {

  • final Object fb = factoryBean;

  • final Method factoryMethod = factoryMethodToUse;

  • final Object[] args = argsToUse;

  • // 通過(guò)執(zhí)行工廠方法來(lái)創(chuàng)建bean示例

  • beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->

  • beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, beanFactory, fb, factoryMethod, args),

  • beanFactory.getAccessControlContext());

  • }

  • else {

  • // 通過(guò)執(zhí)行工廠方法來(lái)創(chuàng)建bean示例

  • beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(

  • mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);

  • }


  • // 包裝為 BeanWraper 對(duì)象

  • bw.setBeanInstance(beanInstance);

  • return bw;

  • }

  • catch (Throwable ex) {

  • throw new BeanCreationException(mbd.getResourceDescription(), beanName,

  • "Bean instantiation via factory method failed", ex);

  • }

  • }

  • instantiateUsingFactoryMethod() 方法體實(shí)在是太大了,處理細(xì)節(jié)感覺(jué)很復(fù)雜,LZ是硬著頭皮看完的,中間斷斷續(xù)續(xù)的。吐槽這里的代碼風(fēng)格,完全不符合我們前面看的 Spring 代碼風(fēng)格。Spring 的一貫做法是將一個(gè)復(fù)雜邏輯進(jìn)行拆分,分為多個(gè)細(xì)小的模塊進(jìn)行嵌套,每個(gè)模塊負(fù)責(zé)一部分功能,模塊與模塊之間層層嵌套,上一層一般都是對(duì)下一層的總結(jié)和概括,這樣就會(huì)使得每一層的邏輯變得清晰易懂。

    回歸到上面的方法體,雖然代碼體量大,但是總體我們還是可看清楚這個(gè)方法要做的事情。一句話概括就是:確定工廠對(duì)象,然后獲取構(gòu)造函數(shù)和構(gòu)造參數(shù),最后調(diào)用 InstantiationStrategy 對(duì)象的 instantiate() 來(lái)創(chuàng)建 bean 實(shí)例。下面我們就這個(gè)句概括的話進(jìn)行拆分并詳細(xì)說(shuō)明。

    確定工廠對(duì)象

    首先獲取工廠方法名,若工廠方法名不為空,則調(diào)用 beanFactory.getBean() 獲取工廠對(duì)象,若為空,則可能為一個(gè)靜態(tài)工廠,對(duì)于靜態(tài)工廠則必須提供工廠類的全類名,同時(shí)設(shè)置 factoryBean=null

    構(gòu)造參數(shù)確認(rèn)

    工廠對(duì)象確定后,則是確認(rèn)構(gòu)造參數(shù)。構(gòu)造參數(shù)的確認(rèn)主要分為三種情況:explicitArgs 參數(shù)、緩存中獲取、配置文件中解析。

    explicitArgs 參數(shù)

    explicitArgs 參數(shù)是我們調(diào)用 getBean() 時(shí)傳遞景來(lái),一般該參數(shù),該參數(shù)就是用于初始化 bean 時(shí)所傳遞的參數(shù),如果該參數(shù)不為空,則可以確定構(gòu)造函數(shù)的參數(shù)就是它了。

    緩存中獲取

    在該方法的最后,我們會(huì)發(fā)現(xiàn)這樣一段代碼: argsHolderToUse.storeCache(mbd,factoryMethodToUse) ,這段代碼主要是將構(gòu)造函數(shù)、構(gòu)造參數(shù)保存到緩存中,如下:

  • public void storeCache(RootBeanDefinition mbd, Executable constructorOrFactoryMethod) {

  • synchronized (mbd.constructorArgumentLock) {

  • mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;

  • mbd.constructorArgumentsResolved = true;

  • if (this.resolveNecessary) {

  • mbd.preparedConstructorArguments = this.preparedArguments;

  • }

  • else {

  • mbd.resolvedConstructorArguments = this.arguments;

  • }

  • }

  • }

  • 其中涉及到的幾個(gè)參數(shù) constructorArgumentLock、resolvedConstructorOrFactoryMethod、constructorArgumentsResolved、resolvedConstructorArguments。這些參數(shù)都是跟構(gòu)造函數(shù)、構(gòu)造函數(shù)緩存有關(guān)的。

    constructorArgumentLock:構(gòu)造函數(shù)的緩存鎖

    resolvedConstructorOrFactoryMethod:緩存已經(jīng)解析的構(gòu)造函數(shù)或者工廠方法

    constructorArgumentsResolved:標(biāo)記字段,標(biāo)記構(gòu)造函數(shù)、參數(shù)已經(jīng)解析了。默認(rèn)為false

    resolvedConstructorArguments:緩存已經(jīng)解析的構(gòu)造函數(shù)參數(shù),包可見(jiàn)字段

    所以從緩存中獲取就是提取這幾個(gè)參數(shù)的值,如下:

  • synchronized (mbd.constructorArgumentLock) {

  • // 獲取緩存中的構(gòu)造函數(shù)或者工廠方法

  • factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;

  • if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {

  • // 獲取緩存中的構(gòu)造參數(shù)

  • argsToUse = mbd.resolvedConstructorArguments;

  • if (argsToUse == null) {

  • // 獲取緩存中的構(gòu)造函數(shù)參數(shù)的包可見(jiàn)字段

  • argsToResolve = mbd.preparedConstructorArguments;

  • }

  • }

  • }

  • 如果緩存中存在構(gòu)造參數(shù),則需要調(diào)用 resolvePreparedArguments() 方法進(jìn)行轉(zhuǎn)換,因?yàn)榫彺嬷械闹涤锌赡苁亲罱K值也有可能不是最終值,比如我們構(gòu)造函數(shù)中的類型為 Integer 類型的 1 ,但是原始的參數(shù)類型有可能是 String 類型的 1 ,所以即便是從緩存中得到了構(gòu)造參數(shù)也需要經(jīng)過(guò)一番的類型轉(zhuǎn)換確保參數(shù)類型完全對(duì)應(yīng)。

    配置文件中解析

    即沒(méi)有通過(guò)傳遞參數(shù)的方式傳遞構(gòu)造參數(shù),緩存中也沒(méi)有,那就只能通過(guò)解析配置文件獲取構(gòu)造參數(shù)了。

    在 bean 解析類的博文中我們了解了,配置文件中的信息都會(huì)轉(zhuǎn)換到 BeanDefinition 實(shí)例對(duì)象中,所以配置文件中的參數(shù)可以直接通過(guò) BeanDefinition 對(duì)象獲取。代碼如下:

  • if (mbd.hasConstructorArgumentValues()) {

  • // 構(gòu)造函數(shù)的參數(shù)

  • ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();

  • resolvedValues = new ConstructorArgumentValues();

  • // 解析構(gòu)造函數(shù)的參數(shù)

  • // 將該 bean 的構(gòu)造函數(shù)參數(shù)解析為 resolvedValues 對(duì)象,其中會(huì)涉及到其他 bean

  • minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);

  • }

  • 通過(guò) BeanDefinition 的 getConstructorArgumentValues() 就可以獲取構(gòu)造信息了,有了構(gòu)造信息就可以獲取相關(guān)的參數(shù)值信息了,獲取的參數(shù)信息包括直接值和引用,這一步驟的處理交由 resolveConstructorArguments()完成,該方法會(huì)將構(gòu)造參數(shù)信息解析為 resolvedValues 對(duì)象 并返回解析到的參數(shù)個(gè)數(shù)。

    構(gòu)造函數(shù)

    確定構(gòu)造參數(shù)后,下一步則是確定構(gòu)造函數(shù)。第一步則是通過(guò) getCandidateMethods() 獲取所有的構(gòu)造方法,同時(shí)對(duì)構(gòu)造方法進(jìn)行刷選,然后在對(duì)其進(jìn)行排序處理( AutowireUtils.sortFactoryMethods(candidates)),排序的主要目的是為了能夠更加方便的找到匹配的構(gòu)造函數(shù),因?yàn)闃?gòu)造函數(shù)的確認(rèn)是根據(jù)參數(shù)個(gè)數(shù)確認(rèn)的。排序的規(guī)則是:public 構(gòu)造函數(shù)優(yōu)先參數(shù)數(shù)量降序、非 public 構(gòu)造參數(shù)數(shù)量降序。

    通過(guò)迭代 candidates(包含了所有要匹配的構(gòu)造函數(shù))的方式,一次比較其參數(shù),如果顯示提供了參數(shù)(explicitArgs != null),則直接比較兩者是否相等,如果相等則表示找到了,否則繼續(xù)比較。如果沒(méi)有顯示提供參數(shù),則需要獲取 ParameterNameDiscoverer 對(duì)象,該對(duì)象為參數(shù)名稱探測(cè)器,主要用于發(fā)現(xiàn)方法和構(gòu)造函數(shù)的參數(shù)名稱。

    將參數(shù)包裝成 ArgumentsHolder 對(duì)象,該對(duì)象用于保存參數(shù),我們稱之為參數(shù)持有者。當(dāng)將對(duì)象包裝成 ArgumentsHolder 對(duì)象后,我們就可以通過(guò)它來(lái)進(jìn)行構(gòu)造函數(shù)匹配,匹配分為嚴(yán)格模式和寬松模式。

    嚴(yán)格模式:解析構(gòu)造函數(shù)時(shí),必須所有參數(shù)都需要匹配,否則拋出異常

    寬松模式:使用具有"最接近的模式"進(jìn)行匹配

    判斷的依據(jù)是根據(jù) BeanDefinition 的 isLenientConstructorResolution 屬性(該參數(shù)是我們?cè)跇?gòu)造 AbstractBeanDefinition 對(duì)象是傳遞的)來(lái)獲取類型差異權(quán)重(typeDiffWeight) 的。如果 typeDiffWeight<minTypeDiffWeight ,則代表“最接近的模式”,選擇其作為構(gòu)造函數(shù),否則只有兩者具有相同的參數(shù)數(shù)量且類型差異權(quán)重相等才會(huì)納入考慮范圍。

    至此,構(gòu)造函數(shù)已經(jīng)確認(rèn)了。

    創(chuàng)建 bean 實(shí)例

    工廠對(duì)象、構(gòu)造函數(shù)、構(gòu)造參數(shù)都已經(jīng)確認(rèn)了,則最后一步就是調(diào)用 InstantiationStrategy 對(duì)象的 instantiate() 來(lái)創(chuàng)建 bean 實(shí)例,如下:

  • public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,

  • @Nullable Object factoryBean, final Method factoryMethod, @Nullable Object... args) {


  • try {

  • if (System.getSecurityManager() != null) {

  • AccessController.doPrivileged((PrivilegedAction<Object>) () -> {

  • ReflectionUtils.makeAccessible(factoryMethod);

  • return null;

  • });

  • }

  • else {

  • ReflectionUtils.makeAccessible(factoryMethod);

  • }


  • Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();

  • try {

  • currentlyInvokedFactoryMethod.set(factoryMethod);

  • // 執(zhí)行工廠方法,并返回實(shí)例

  • Object result = factoryMethod.invoke(factoryBean, args);

  • if (result == null) {

  • result = new NullBean();

  • }

  • return result;

  • }

  • finally {

  • if (priorInvokedFactoryMethod != null) {

  • currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);

  • }

  • else {

  • currentlyInvokedFactoryMethod.remove();

  • }

  • }

  • }

  • // 省略一波 catch

  • }

  • instantiate() 最核心的部分就是利用 Java 反射執(zhí)行工廠方法并返回創(chuàng)建好的實(shí)例,也就是這段代碼:

  • Object result = factoryMethod.invoke(factoryBean, args);

  • 到這里 instantiateUsingFactoryMethod() 已經(jīng)分析完畢了,這里 LZ 有些題外話需要說(shuō)下,看源碼真心是一個(gè)痛苦的過(guò)程,尤其是復(fù)雜的源碼,比如這個(gè)方法我看了三天才弄清楚點(diǎn)皮毛,當(dāng)然這里跟 LZ 的智商有些關(guān)系(智商捉急 ┭┮﹏┭┮),寫(xiě)這篇博客也花了五天時(shí)間才寫(xiě)完(最后截稿日為:2018.08.10 01:23:49),所以每一個(gè)堅(jiān)持寫(xiě)博客的都是折翼的天使,值得各位尊敬

    createBeanInstance() 還有兩個(gè)重要方法 autowireConstructor() 和 instantiateBean() ,由于篇幅問(wèn)題,所以將這兩個(gè)方法放在下篇博客分析。敬請(qǐng)期待!!!


    原文發(fā)布時(shí)間為:2018-10-31
    本文作者:Java技術(shù)驛站
    本文來(lái)自云棲社區(qū)合作伙伴“Java技術(shù)驛站”,了解相關(guān)信息可以關(guān)注“Java技術(shù)驛站”。

    總結(jié)

    以上是生活随笔為你收集整理的【死磕 Spring】—– IOC 之 Factory 实例化 bean的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    国产精品一区二区你懂的 | jizz欧美性9 国产一区高清在线观看 | 9i看片成人免费看片 | 亚洲国产中文在线观看 | 韩国精品在线观看 | 韩国精品福利一区二区三区 | 久久人操 | 欧美日bb | 亚州人成在线播放 | 精精国产xxxx视频在线播放 | 91精品啪在线观看国产线免费 | 中文字幕在线看人 | 中文字幕在线免费播放 | 日本黄色免费在线 | www久久国产 | 国产精品久久久久久久久久不蜜月 | 97在线观看视频国产 | 五月激情姐姐 | 国产亚洲精品久久19p | 国产精品精品久久久久久 | 午夜av色| 色综合久久久久综合体桃花网 | 国产精品电影一区二区 | www.五月婷婷 | 国产精品久久久久av免费 | 欧美先锋影音 | 在线视频 区 | 欧美成人区 | 成人av在线网址 | 久久视影| 欧美一区二区三区激情视频 | 97视频人人免费看 | 亚洲日本va午夜在线影院 | 久草资源在线观看 | 99中文视频在线 | 麻豆av一区二区三区在线观看 | 国产区在线看 | 黄色毛片一级 | 久久久精品成人 | 亚洲h视频在线 | 丁香av在线 | 免费成人黄色片 | 午夜影院三级 | 亚洲黄污| 中文字幕一区二区三区乱码在线 | 免费观看久久久 | 激情视频免费在线 | 天天综合网入口 | 黄色一级大片在线免费看产 | 麻豆免费视频网站 | 免费人成网ww44kk44 | 日韩精品免费在线观看 | 中文字幕av在线 | 在线成人免费 | 国产一级a毛片视频爆浆 | 五月香视频在线观看 | 99人成在线观看视频 | 色就色,综合激情 | 免费日韩一级片 | 亚洲一二三区精品 | 人人爽人人爽人人片av免 | 欧美激情在线看 | a视频在线看| 中文字幕在线视频免费播放 | 亚洲成人av免费 | 欧美激情另类 | 久久久久久国产精品 | 黄色一集片 | 亚洲成人av在线播放 | 中文字幕在线日亚洲9 | 伊人色综合久久天天 | 天天干中文字幕 | 天天干国产 | 日韩久久久久久 | 婷婷色狠狠 | 99久久综合狠狠综合久久 | 欧美国产日韩久久 | 成人一区二区三区在线 | 日本狠狠色 | 免费观看成人 | 婷婷色伊人 | 最新91在线视频 | 欧美色噜噜噜 | 日韩免费小视频 | 久久久久久久久久久成人 | 久精品视频 | 91香蕉视频720p | 99久久久久久久久 | 久久精品99国产精品酒店日本 | 99精品欧美一区二区 | 草久草久| 欧美国产大片 | 亚洲欧美国产日韩在线观看 | 又黄又爽的视频在线观看网站 | 狠狠操狠狠干2017 | 99re久久资源最新地址 | 黄色小说网站在线 | 国产麻豆精品久久 | 最近高清中文在线字幕在线观看 | 成年人在线播放视频 | 日本中文字幕观看 | 久久精品一区二区三区国产主播 | 免费a级观看 | 国产精品综合久久久久久 | 在线播放91 | 亚洲国产日韩一区 | 色噜噜在线观看视频 | 日韩乱色精品一区二区 | 99视频免费| 91在线视频在线 | 五月婷婷毛片 | 在线观av | 狠狠躁18三区二区一区ai明星 | 99精品国产高清在线观看 | 国产精品毛片一区二区在线 | 日批视频在线观看免费 | 免费高清在线观看电视网站 | 在线网站黄 | 黄色成人在线观看 | 婷婷激情欧美 | 久久免视频 | 欧美日韩高清不卡 | 日韩高清在线一区二区 | 蜜臀av性久久久久av蜜臀妖精 | 国产最顶级的黄色片在线免费观看 | 99久久婷婷 | 蜜臀91丨九色丨蝌蚪老版 | 成片人卡1卡2卡3手机免费看 | 五月天久久综合 | 激情五月婷婷丁香 | 嫩嫩影院理论片 | 国产美女视频网站 | 四虎在线视频 | 国产精品亚洲片夜色在线 | 日韩h在线观看 | 五月婷婷综合在线 | 日日夜夜狠狠操 | 久99久中文字幕在线 | 字幕网在线观看 | 在线精品一区二区 | 亚洲涩涩涩 | 国产小视频你懂的 | 亚洲精品视频免费看 | 日韩中文字幕视频在线观看 | 国产九九精品 | 国产一级片观看 | 五月激情站| 中文字幕在线观看第三页 | 久久精品99精品国产香蕉 | 一级片在线 | 中文字幕 第二区 | 91在线免费视频观看 | 97视频免费看| 人人超在线公开视频 | 国产精品免费在线观看视频 | 黄色av网站在线免费观看 | 成人av免费在线看 | 亚洲午夜久久久影院 | 日本精品在线 | 国产精品成人一区二区三区吃奶 | 久久精品国产第一区二区三区 | 久久成人资源 | 亚洲精品五月 | 日本久热| 欧美日本中文字幕 | 91久久国产综合精品女同国语 | 日韩视频一区二区三区 | 精品国产亚洲日本 | 婷婷视频导航 | 国产精品久久99综合免费观看尤物 | 日韩在线观看影院 | 国产精品观看在线亚洲人成网 | 激情电影影院 | 亚洲欧美日本一区二区三区 | 免费在线国产精品 | 国产精品第一视频 | 一级做a爱片性色毛片www | 亚洲91视频| 久久国产精品免费一区二区三区 | 黄色影院在线免费观看 | a级国产乱理伦片在线播放 久久久久国产精品一区 | 日韩免费观看视频 | 丰满少妇在线观看网站 | 91在线看片 | 日韩毛片在线播放 | 欧美夫妻性生活电影 | 狠狠的操狠狠的干 | 国产成人精品不卡 | 波多野结衣视频在线 | 高清中文字幕 | 毛片久久久| 色欧美成人精品a∨在线观看 | 98涩涩国产露脸精品国产网 | 国产一卡二卡在线 | 在线观看国产一区二区 | 日韩精品偷拍 | 国产精品女人久久久 | 在线影院 国内精品 | 久久久久久久久国产 | 黄网站免费大全入口 | 制服丝袜在线 | 亚洲精品国产综合99久久夜夜嗨 | 成人性生爱a∨ | 99久久99| 黄色免费视频在线观看 | 91精品免费视频 | 久久69精品久久久久久久电影好 | 正在播放国产91 | 欧美成年性 | 成人久久影院 | 久久91久久久久麻豆精品 | 国产精品久久99综合免费观看尤物 | 午夜精品一区二区三区免费 | 在线观看国产亚洲 | 很黄很污的视频网站 | 国产精品久久久影视 | 精品久久久久国产免费第一页 | 成人免费在线电影 | 91在线免费观看国产 | 成年人免费在线观看网站 | 五月激情电影 | 91麻豆精品国产自产在线游戏 | 久久综合射 | 日韩在线观看 | 美女网站视频免费都是黄 | 97免费| 成人在线免费看 | 91av国产视频| 91av久久| 国产 一区二区三区 在线 | 国产精品免费一区二区三区 | 在线观看91视频 | 黄色网址国产 | 国产精品短视频 | 色综合天天色 | 国产一级免费观看视频 | 欧美色综合天天久久综合精品 | 日韩二区在线观看 | 一级黄色网址 | 欧美综合色 | 国产成人一二片 | 欧美性久久久久久 | 婷婷射五月 | 国产a级精品 | 91福利免费 | 狠狠干夜夜操 | 天天爽夜夜爽人人爽一区二区 | 成人在线视频一区 | 婷婷精品在线视频 | 91成人天堂久久成人 | 18av在线视频 | 最近中文字幕久久 | 美女网站视频色 | 日日操夜夜操狠狠操 | 亚洲深夜影院 | 天天操综合 | 国产成人精品国内自产拍免费看 | 国产精品手机在线观看 | 亚洲视频免费在线观看 | 中文字幕一区在线观看视频 | 欧美大片mv免费 | 玖玖在线观看视频 | www.久久99| 伊人天天狠天天添日日拍 | 婷婷激情在线 | 亚洲欧美偷拍另类 | 91精品国自产在线偷拍蜜桃 | 亚洲九九九在线观看 | 91爱在线| 久久国产精品久久精品国产演员表 | 成+人+色综合 | 日韩av中文在线 | 国产毛片久久久 | 婷婷亚洲五月 | 国产高清综合 | 久久经典国产 | 99久久精品免费看国产麻豆 | 久久涩涩网站 | 在线看小早川怜子av | 四虎影视精品永久在线观看 | 欧美日韩一区二区视频在线观看 | 成人a在线观看 | 亚洲专区在线 | 欧美国产精品久久久久久免费 | 国产精品久久久久久久午夜片 | 在线色吧| 天天干天天搞天天射 | 日日操日日操 | 成人a毛片 | 91丨九色丨丝袜 | 美女网站免费福利视频 | 一区二区不卡 | 日韩欧美视频一区二区 | 天天在线视频色 | 五月天亚洲综合小说网 | 狠狠色丁香婷婷综合久小说久 | 黄色av一区二区 | 精品一区二区三区电影 | 欧美激情综合色综合啪啪五月 | 91av福利视频| 二区三区在线观看 | 亚洲欧美色婷婷 | 在线观看免费色 | 成人黄色大片在线免费观看 | 园产精品久久久久久久7电影 | 91av中文 | 欧美精品少妇xxxxx喷水 | 国产精品video爽爽爽爽 | 大胆欧美gogo免费视频一二区 | 婷婷国产在线观看 | 在线成人小视频 | 亚洲最大的av网站 | 91精品国产一区二区三区 | 亚洲精品字幕在线观看 | 人人玩人人爽 | 亚洲精品久久久久久久蜜桃 | 色偷偷网站视频 | 欧美日韩调教 | 99视频在线看 | 丁香激情综合国产 | 午夜精品视频免费在线观看 | 综合网伊人 | www.福利| av不卡免费在线观看 | 国产欧美日韩视频 | 天天干天天做天天操 | 国产精品青草综合久久久久99 | 在线观看网站你懂的 | 高清av在线 | 色欧美视频| 国产精品一区二区吃奶在线观看 | www色com| 色99网 | 国产日韩精品久久 | av中文在线影视 | 99国产精品久久久久老师 | 国产视频一区二区在线播放 | 国产午夜三级一区二区三桃花影视 | 午夜精品久久久久久久99无限制 | 国产精品国产三级在线专区 | 成人欧美一区二区三区在线观看 | 精品久久久久久久久久久久久久久久久久 | 99久久精品一区二区成人 | 欧美性生活免费 | 四虎在线影视 | 日韩精品久久久久久久电影99爱 | 91看片看淫黄大片 | 91久久丝袜国产露脸动漫 | 成人在线视频网 | 日韩免费不卡av | 69av国产| 欧美激情视频一区 | 99久久精品一区二区成人 | 免费看一级黄色 | 国产精品乱码久久久久 | 中文字幕国产 | 热99久久精品 | 国产女教师精品久久av | 久久亚洲私人国产精品 | 久久精品99国产精品日本 | 丁香花中文字幕 | 黄色h在线观看 | 黄色在线视频网址 | 亚洲,播放 | 日韩免费一二三区 | 在线影视 一区 二区 三区 | 国产91在线看 | 激情欧美一区二区三区免费看 | www免费看| 亚洲色图27p | 久久夜色网| 亚洲午夜久久久久久久久久久 | 欧美日韩一区二区三区不卡 | 国产色 在线 | 亚洲区另类春色综合小说校园片 | 国产精品日韩在线观看 | 一区二区免费不卡在线 | 一区二区三区日韩在线观看 | 久久久伊人网 | 干天天| 国产在线999 | 夜夜干夜夜 | 久久99精品久久只有精品 | 高清av免费看 | 国产日韩三级 | 96av视频| 亚洲精品99久久久久久 | 日日躁夜夜躁xxxxaaaa | 久久久国产一区 | 99精品国产免费久久 | 国产网红在线观看 | 精品一区二区三区香蕉蜜桃 | 亚洲乱码国产乱码精品天美传媒 | 国产精品免费一区二区 | 91视频一8mav | 日日操网 | 亚洲国产精品影院 | 天天干,天天干 | 国产高清专区 | 亚洲精品影院在线观看 | 久久久久www | av在线等 | 亚洲精品456在线播放第一页 | 久久久久久看片 | 日韩一二三区不卡 | 肉色欧美久久久久久久免费看 | 中文字幕亚洲综合久久五月天色无吗'' | 九九欧美视频 | 91av在线免费播放 | 国产免费一区二区三区网站免费 | 国产精品久久久久999 | 91精品久久久久久粉嫩 | 久久视频这里有久久精品视频11 | 国产a级片免费观看 | 在线看v片 | 国产日韩精品一区二区三区在线 | 福利一区二区 | 成人久久久精品国产乱码一区二区 | 国产在线中文字幕 | 四虎成人免费影院 | 亚洲成人精品久久久 | 婷婷av网站 | 人人狠狠综合久久亚洲婷 | 精品亚洲一区二区 | 免费看成年人 | 久要激情网| 中文字幕一区二区三区久久 | 最新av免费在线 | 午夜精品一区二区三区视频免费看 | h动漫中文字幕 | 午夜久久久精品 | 婷婷六月色 | 免费观看的av网站 | 国产免费嫩草影院 | 亚洲一一在线 | 五月天免费网站 | 日日干夜夜干 | 在线看国产日韩 | 最新日本中文字幕 | av成人亚洲| 黄色亚洲免费 | av先锋影音少妇 | 91综合久久一区二区 | 天天干天天天 | 精品视频免费播放 | 五月天婷婷在线播放 | av网站大全免费 | 少妇bbw揉bbb欧美 | 亚洲精品女 | 国模一区二区三区四区 | 在线看片成人 | 久久精品三 | 亚洲五月婷婷 | 一区二区激情视频 | 日韩一级黄色av | 国产精品精品久久久久久 | 狠狠操欧美 | 成人h动漫在线看 | 国产3p视频 | 成人国产精品入口 | 香蕉视频免费看 | 亚洲成aⅴ人在线观看 | 久久精品一区二区 | av免费观看高清 | 成人精品国产免费网站 | 中文字幕av一区二区三区四区 | 伊人婷婷久久 | 天天爱天天操天天射 | www.狠狠插.com | 免费视频a | 日本久久久久久久久久 | 精品高清视频 | 国产精品手机看片 | 人人艹人人 | 国产很黄很色的视频 | 中文字幕av免费在线观看 | 久久任你操 | 99 久久久久 | 久久久午夜精品理论片中文字幕 | 欧美久久久久久久久中文字幕 | 国产成人综合精品 | 日韩一区二区三区免费视频 | 国产精品视频久久久 | 最近中文字幕免费大全 | 麻豆精品国产传媒 | 片网站 | 96精品高清视频在线观看软件特色 | 黄色大全免费网站 | 婷婷在线网 | 精品国偷自产在线 | 成年人视频在线免费观看 | 亚洲精品美女久久久久网站 | 日韩欧美视频免费看 | 久久久久久久久久久影视 | 99在线视频播放 | 91视频这里只有精品 | 久久99久久久久久 | 97碰在线| www.天天操.com | 日韩电影在线观看一区二区三区 | bbw av | 欧美a级一区二区 | 精品美女久久久久久免费 | 国产视频在线免费 | 久久a级片 | 免费在线电影网址大全 | 在线成人一区 | 成人啊 v | 久久久久久久久久亚洲精品 | 亚洲综合网站在线观看 | 免费在线观看av片 | 最新免费av在线 | 91精品国产网站 | 超碰97人人爱 | 超碰在线个人 | 91黄色免费看 | 中文超碰字幕 | 婷婷激情综合 | 中文字幕av在线免费 | 欧美aaaxxxx做受视频 | 久久精品4 | 日本99干网 | 激情婷婷 | a色网站 | 五月婷网站 | 午夜黄网 | 99视频在线精品国自产拍免费观看 | 国产黄色在线观看 | 成人一区不卡 | 日韩v欧美v日本v亚洲v国产v | 这里只有精品视频在线观看 | 色欧美综合 | 在线欧美日韩 | 免费黄av| 日韩高清不卡在线 | 亚洲成免费| 国产高清成人 | 国产日韩欧美在线影视 | 欧美极品少妇xxxx | 欧美日韩中文在线 | 91色在线观看 | 国产高h视频 | 婷五月天激情 | 日韩高清免费在线观看 | av在线免费观看黄 | 国产在线91在线电影 | 国产中文字幕在线播放 | 福利片视频区 | 正在播放国产一区二区 | 久久一久久 | 91亚洲夫妻| 看国产黄色片 | 久久伊人91 | 久久草在线视频国产 | 在线观看视频99 | 亚洲欧美视频在线观看 | 免费视频91蜜桃 | 9999精品免费视频 | 欧美精品久久久久久 | 亚洲国产一二三 | 欧美日韩视频在线观看一区二区 | 欧美性超爽| 国产一区免费在线 | 丁香六月婷婷 | 亚洲激情电影在线 | 99精品久久精品一区二区 | 夜夜夜夜夜夜操 | 三级动图| 亚洲免费高清视频 | 久久久久女人精品毛片 | 亚洲国产av精品毛片鲁大师 | 久久婷亚洲五月一区天天躁 | 免费福利视频网 | 国产午夜三级一区二区三桃花影视 | 91成人免费视频 | 日韩色综合网 | 久久久久女人精品毛片 | 日韩欧美精品免费 | 欧美成人精品在线 | 久久精品爱爱视频 | 精品视频亚洲 | 在线视频在线观看 | a黄色影院 | 丝袜制服天堂 | 99国产精品一区二区 | 久久国产亚洲精品 | 国产不卡在线视频 | 最新国产精品久久精品 | 中文字幕在线观看网址 | 免费在线观看91 | 精品国产一区二区三区久久 | 久久人91精品久久久久久不卡 | 天天插综合| 人人操日日干 | 国产视频亚洲视频 | 国产精品久久久久aaaa | 中文字幕人成乱码在线观看 | 人人澡人人模 | 亚洲va欧洲va国产va不卡 | 白丝av在线 | 黄色毛片在线观看 | 日韩系列在线观看 | 久久久久久国产精品 | 主播av在线 | 四虎永久精品在线 | 国产精品高潮久久av | 日韩二区三区在线观看 | 欧美做受高潮电影o | 色综合天天做天天爱 | 精品福利在线观看 | 国产一区二区三区久久久 | 99久久精品国产一区二区三区 | 成人网在线免费视频 | 久久精品国产免费 | 久草久草视频 | 国产护士hd高朝护士1 | 久久久久国产a免费观看rela | 成人精品一区二区三区电影免费 | 操高跟美女 | 狠狠的干| av在线日韩| 精品国产电影一区 | 日本h视频在线观看 | 欧美日韩中文国产 | 免费成人在线观看视频 | 国产在线1区 | 国外调教视频网站 | av久久在线 | 在线视频1卡二卡三卡 | 国产免费一区二区三区最新6 | 色多多视频在线观看 | 亚洲夜夜网 | 亚洲精品99久久久久久 | 一级精品视频在线观看宜春院 | 久久久久麻豆v国产 | 在线观看国产中文字幕 | 欧洲成人免费 | 久久激情综合 | 丝袜少妇在线 | 国产亚洲精品福利 | 在线看片中文字幕 | 国产尤物在线观看 | 午夜免费在线观看 | 日韩欧美在线一区二区 | 天天干夜夜想 | 亚洲毛片一区二区三区 | 色综合夜色一区 | 国产午夜精品av一区二区 | 国产一级精品绿帽视频 | 国产精品一区二区三区视频免费 | 中文字幕在线观看完整版电影 | 亚洲最大在线视频 | 在线观看视频国产 | 成人高清av在线 | 天天色天天干天天 | 欧美色伊人 | 成人黄色在线 | 日韩欧美精品在线视频 | 欧美日韩在线观看一区二区 | 中文字幕亚洲精品日韩 | 国产精成人品免费观看 | 91自拍视频在线 | 欧美激情视频在线免费观看 | 亚洲影视资源 | 亚洲日本va午夜在线电影 | 国产69精品久久99不卡的观看体验 | 911精品美国片911久久久 | 日韩在线观看一区二区三区 | 91免费视频国产 | 免费日韩三级 | 69精品在线观看 | 亚洲播播 | 欧美日韩二三区 | free. 性欧美.com | av久久久久久 | 人人爽人人舔 | 四虎成人精品在永久免费 | 探花视频在线观看免费版 | 久久私人影院 | 久久69av | 日本成人黄色片 | 日日干天天射 | 日韩欧美在线一区 | 99在线热播精品免费99热 | 国产精品午夜免费福利视频 | 97品白浆高清久久久久久 | 青草视频在线免费 | 探花视频免费观看高清视频 | 午夜影院在线观看18 | 国内综合精品午夜久久资源 | 亚洲精品在线二区 | 亚洲日本欧美 | 久久精品国产亚洲a | 国产日韩精品视频 | 精品国产免费看 | 黄色片软件网站 | 一级特黄av | 一本一道波多野毛片中文在线 | 在线免费观看一区二区三区 | 日韩一区二区三区不卡 | 免费开视频| 丁香婷婷射 | 四虎国产永久在线精品 | 色婷在线| 天天摸天天操天天舔 | 亚洲精品www. | 亚洲精品tv久久久久久久久久 | 亚洲免费不卡 | 久久99精品波多结衣一区 | 亚洲精品综合一二三区在线观看 | 欧美亚洲精品在线观看 | 在线观看黄色免费视频 | 久久久久久久久久影院 | 欧美日韩一二三四区 | 91九色在线播放 | 精品久久久精品 | 狠狠色丁婷婷日日 | 色视频网页| 日韩av有码在线 | 午夜狠狠操 | 久久y| 日韩精品一区二区三区电影 | 亚洲a在线观看 | 最近日韩免费视频 | 992tv人人网tv亚洲精品 | 午夜美女福利直播 | 香蕉视频在线观看免费 | 日日噜噜噜噜夜夜爽亚洲精品 | 色人久久 | 国内99视频 | 97超碰在线资源 | 娇妻呻吟一区二区三区 | 久久99精品一区二区三区三区 | av在线播放一区二区三区 | 欧美日韩视频在线 | 毛片永久免费 | 中文字幕制服丝袜av久久 | 91麻豆精品国产自产 | 日本少妇高清做爰视频 | av电影久久 | 91大神免费在线观看 | 啪啪资源 | 日韩精品一区二区三区在线视频 | 国内一区二区视频 | 婷婷 中文字幕 | 亚洲欧美日韩在线一区二区 | 久久免费视频6 | 精品视频在线免费观看 | 精品久久久久免费极品大片 | 免费一级特黄毛大片 | 欧美激情视频一二三区 | 午夜婷婷在线播放 | 午夜久久美女 | 国产视频欧美视频 | 国偷自产中文字幕亚洲手机在线 | 国产色视频网站 | 欧美精品乱码久久久久久 | 久久久久美女 | 九七视频在线观看 | 免费观看全黄做爰大片国产 | 国产精品美女久久久久久久 | 久99久精品| 欧美久久九九 | 久久久久久久久久久久久国产精品 | av电影不卡在线 | 久久精品99久久久久久2456 | 又色又爽又黄高潮的免费视频 | 狠狠撸电影 | www.黄色网.com | 国内外成人在线 | 日日干av | 操高跟美女 | 日韩乱码在线 | 日韩美一区二区三区 | 国产精品无av码在线观看 | 人成在线免费视频 | 国产操在线 | 久久免费视频国产 | 成人一级片视频 | 伊人春色电影网 | 国产999精品久久久久久绿帽 | 日韩电影久久 | 久久九九九九 | 国产成人61精品免费看片 | 日韩激情av在线 | 中文字幕在线观看第一区 | 欧美日本不卡高清 | 亚洲最大av | 毛片无卡免费无播放器 | 人人超碰免费 | 丝袜制服天堂 | 久久黄色影院 | 成人黄色电影免费观看 | a在线免费观看视频 | 免费在线观看午夜视频 | 亚洲天天做 | 免费成人av| 午夜精品久久久久99热app | 国产精品成人免费精品自在线观看 | 在线视频你懂得 | 国产精品久久久久久久婷婷 | 黄色三级网站 | 国产亚洲成av人片在线观看桃 | 狠狠操夜夜操 | 天天色天天 | 青青色影院 | 亚洲精品中文在线观看 | 久草精品在线播放 | 久久久久久久精 | 国产一级高清视频 | 天天综合视频在线观看 | 久久久久免费精品国产小说色大师 | 免费看成人 | 91精品国自产在线偷拍蜜桃 | 久久精品视频在线免费观看 | 久久久99精品免费观看app | 成人一级片视频 | 国产精品视频地址 | av中文字幕网站 | 激情视频综合网 | 黄色大片av | 免费看一及片 | 奇米网444 | 亚洲精品国产精品国自产观看 | 欧美日韩一区三区 | av大片网址 | 四虎国产精品免费观看视频优播 | 91免费的视频在线播放 | 免费三级黄色片 | avove黑丝| 国产视频中文字幕在线观看 | 国产资源av| 国产1区2区3区精品美女 | 国产精品乱码一区二三区 | 国产精品九九九九九九 | 国产精品久久久久av福利动漫 | 成人免费视频网 | 中文字幕在线看视频国产 | 亚洲一区二区精品视频 | 精品乱码一区二区三四区 | 精品国产伦一区二区三区免费 | 97精品国产91久久久久久 | 91福利视频在线 | 午夜视频在线观看一区二区 | 国内精品久久久久 | 99爱这里只有精品 | 九九热中文字幕 | 国产精品女 | 黄色软件在线观看免费 | 91在线观看高清 | 免费在线成人av | 国产亚洲人成网站在线观看 | 欧美日韩高清一区二区 国产亚洲免费看 | 91尤物国产尤物福利在线播放 | 91精品福利在线 | 国产精品一区二区久久国产 | 成人av电影在线播放 | 国产精品精品久久久 | 久久久久久高潮国产精品视 | 中文字幕免费高清av | 免费看一级特黄a大片 | 99成人免费视频 | 97超碰影视 | av电影久久 | 国产精品久久久av | 久久综合久久综合九色 | 欧美成人黄 | 亚洲国产精品女人久久久 | 亚洲最新av在线网站 | 国产黄色av影视 | 综合色影院 | 美女视频黄色免费 | 久久久黄视频 | 久久久精品影视 | 中文一区二区三区在线观看 | 91av电影| 国产破处在线视频 | 国内视频 | 在线观看精品一区 | 国内精品久久久久久久久久久 | 在线中文字幕电影 | 六月激情久久 | 亚洲国产欧美在线人成大黄瓜 | 亚洲精品视频免费在线 | 日本少妇高清做爰视频 | 成人黄色av免费在线观看 | 国产对白av | 日本老少交| 国产99久久九九精品免费 | 免费黄在线看 | 亚洲成av人片在线观看 | 中文字幕亚洲五码 | 中文字幕中文字幕在线一区 | 久久精品影片 | 91久久在线观看 | 国产资源免费在线观看 | 成人免费电影 | 91激情视频在线播放 | 午夜影院先| 国产成人精品av在线 | 天天躁日日躁狠狠躁av中文 | 亚洲精品tv | 久久久久综合网 | 欧美国产日韩激情 | 久草在线免费色站 | 91精品日韩 | 国产成人免费 | 天天射天天操天天干 | 香蕉久草在线 | 香蕉视频久久久 | 最新国产在线观看 | 亚洲国产日韩精品 | 夜夜夜夜猛噜噜噜噜噜初音未来 | 在线观看一级 | 欧美一级久久久 | 福利片视频区 | 免费在线观看亚洲视频 | 久久久久9999亚洲精品 | www色网站 | 999超碰 | 一区二区三区免费在线观看视频 | 精品中文字幕在线观看 | 婷婷久月| 久久午夜精品视频 | 97夜夜澡人人双人人人喊 | 西西大胆免费视频 | 欧美日韩视频精品 | 一级免费黄视频 | 色综合久久综合中文综合网 | 四虎国产精品成人免费4hu | 女人高潮一级片 | 国产精品99久久久 | 天天操·夜夜操 | 国产中文字幕在线免费观看 | 五月天综合网站 | 美女久久视频 | 欧美 日韩 性 | 免费在线视频一区二区 | 91麻豆精品国产91久久久久 | 91日韩精品视频 | 亚洲欧美日韩国产精品一区午夜 | 成人免费观看视频网站 | 亚洲免费视频观看 | 欧美韩国日本在线观看 | 国产一级免费视频 | 超级av在线| 三级黄色免费 | 午夜黄网| 伊人亚洲综合 | 欧美三级在线播放 | 久久久91精品国产一区二区精品 | 在线免费高清一区二区三区 | 日韩在线观看网站 | 亚洲欧洲美洲av | 亚洲精品久久久蜜桃直播 | 又紧又大又爽精品一区二区 | 开心色激情网 | 麻豆手机在线 | 日韩精品无 | 国产精品第二十页 | 午夜18视频在线观看 | 日韩免费小视频 | 麻豆极品| 国内精品久久久久 | 免费在线观看毛片网站 | 久久久久久久久久久久久9999 | 伊人久久电影网 | 亚洲激情综合 | 亚州黄色一级 | 丁香激情婷婷 | 色综久久 | 国产九九九精品视频 | 蜜臀av一区| 久久精品国产成人精品 | 91成人黄色 | 国产成人三级在线观看 | 九九精品视频在线观看 | 国产日韩在线一区 | 五月婷亚洲 | 97国产精品一区二区 | 久久综合狠狠综合久久综合88 | 久久尤物电影视频在线观看 | 天天操网站 | a视频免费看| 国产成人61精品免费看片 | 久久久久成人精品免费播放动漫 | 91九色国产视频 | 丁香5月婷婷久久 | 视频直播国产精品 | 日女人电影 | 黄色大片视频网站 | 久久精品伊人 | 亚洲午夜久久久久久久久 | 中文字幕一区二区三区四区 | 亚洲综合在线播放 | 国产色爽| 在线一区观看 | 国产成人一区二区三区久久精品 |