国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

優(yōu)化網(wǎng)站哪家好競價排名是按照什么來計費的

優(yōu)化網(wǎng)站哪家好,競價排名是按照什么來計費的,安陽網(wǎng)站建設(shè)報價,123網(wǎng)址大全我們知道通過類進行修復(fù)不同的屬性,比如單例、原型等,而具體的流程是怎么樣的呢,這一篇我們開始從源碼的視角分析以下。 刷新方法 在刷新容器中有一個方法,其實就是 Bean創(chuàng)建的過程。 finishBeanFactoryInitialization(beanFact…

我們知道通過類進行修復(fù)不同的屬性,比如單例、原型等,而具體的流程是怎么樣的呢,這一篇我們開始從源碼的視角分析以下。

刷新方法

在刷新容器中有一個方法,其實就是 Bean創(chuàng)建的過程。

	finishBeanFactoryInitialization(beanFactory);

finishBeanFactoryInitialization

	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// 給工廠設(shè)置好 ConversionService【負責(zé)類型轉(zhuǎn)換的組件服務(wù)】, Initialize conversion service for this context.if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}// 注冊一個默認的值解析器("${}")  ;Register a default embedded value resolver if no BeanFactoryPostProcessor// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:// at this point, primarily for resolution in annotation attribute values.if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));}// LoadTimeWeaverAware;aspectj:加載時織入功能【aop】。 Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName); //從容器中獲取組件,有則直接獲取,沒則進行創(chuàng)建}// Stop using the temporary ClassLoader for type matching.beanFactory.setTempClassLoader(null);// Allow for caching all bean definition metadata, not expecting further changes.beanFactory.freezeConfiguration();// Instantiate all remaining (non-lazy-init) singletons.//初始化所有的非懶加載的單實例BeanbeanFactory.preInstantiateSingletons(); //這里是重點}

而BeanFactory中 preInstantiateSingletons是初始化所有的bean對象的核心流程。

	public void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}// Iterate over a copy to allow for init methods which in turn register new bean definitions.// While this may not be part of the regular factory bootstrap, it does otherwise work fine.List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// 創(chuàng)建出所有的單實例Bean;Trigger initialization of all non-lazy singleton beans...for (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); //開始解析文件的時候每一個bean標(biāo)簽被解析封裝成一個BeanDefinitionif (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) { //如果是FactoryBean則執(zhí)行下面邏輯Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); //得到HelloFactoryif (bean instanceof FactoryBean) {FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}}else { //不是FactoryBean則執(zhí)行這個,普通的單實例非懶加載bean的創(chuàng)建getBean(beanName); //核心流程}}}// 觸發(fā) post-initialization 邏輯;  Trigger post-initialization callback for all applicable beans...for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}smartInitialize.end();}}}

而這里通過去遍歷所有的bean去進行創(chuàng)建,顯示判斷是isFactoryBean 還是普通bean。顯然我們創(chuàng)建的是普通的bean對象。

doGetBean

	protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {String beanName = transformedBeanName(name); //轉(zhuǎn)換Bean名字Object beanInstance;// 先檢查單實例bean的緩存 Eagerly check singleton cache for manually registered singletons.Object sharedInstance = getSingleton(beanName); //檢查緩存中有沒有,如果是第一次獲取肯定是沒有的if (sharedInstance != null && args == null) {if (logger.isTraceEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.trace("Returning cached instance of singleton bean '" + beanName + "'");}}beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else { //默認第一次獲取組件都會進入else環(huán)節(jié)// Fail if we're already creating this bean instance:// We're assumably within a circular reference.if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// 拿到整個beanFactory的父工廠;看父工廠沒有,從父工廠先嘗試獲取組件; Check if bean definition exists in this factory.BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { //以下開始從父工廠獲取組件// Not found -> check parent.String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}else if (args != null) {// Delegation to parent with explicit args.return (T) parentBeanFactory.getBean(nameToLookup, args);}else if (requiredType != null) {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}else {return (T) parentBeanFactory.getBean(nameToLookup);}}if (!typeCheckOnly) {markBeanAsCreated(beanName); //標(biāo)記當(dāng)前beanName的bean已經(jīng)被創(chuàng)建}StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);try {if (requiredType != null) {beanCreation.tag("beanType", requiredType::toString);}RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dep : dependsOn) { //看當(dāng)前Bean有沒有依賴其他Beanif (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}registerDependentBean(dep, beanName);try {getBean(dep); //依賴了其他bean,就先獲取其他的哪些bean}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}// 創(chuàng)建bean的實例;Create bean instance.if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);  //創(chuàng)建bean對象的實例}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}}); //看當(dāng)前bean是否是FactoryBeanbeanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}else {String scopeName = mbd.getScope();if (!StringUtils.hasLength(scopeName)) {throw new IllegalStateException("No scope name defined for bean ′" + beanName + "'");}Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new ScopeNotActiveException(beanName, scopeName, ex);}}}catch (BeansException ex) {beanCreation.tag("exception", ex.getClass().toString());beanCreation.tag("message", String.valueOf(ex.getMessage()));cleanupAfterBeanCreationFailure(beanName);throw ex;}finally {beanCreation.end();}}//轉(zhuǎn)Object為Bean的T類型return adaptBeanInstance(name, beanInstance, requiredType);}

這里的核心流程其實是先從Bean工廠是否獲取到,如果沒有的話判斷具體的Bean類型,是單例、原型、還是其他。而單例Bean獲取的時候,其實使用了雙檢查鎖。

	protected Object getSingleton(String beanName, boolean allowEarlyReference) {//先檢查單例緩存池,獲取當(dāng)前對象  Quick check for existing instance without full singleton lockObject singletonObject = this.singletonObjects.get(beanName); //一級緩存if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { //如果當(dāng)前bean正在創(chuàng)建過程中,而且緩存中沒有則繼續(xù)singletonObject = this.earlySingletonObjects.get(beanName); //二級if (singletonObject == null && allowEarlyReference) {synchronized (this.singletonObjects) {// Consistent creation of early reference within full singleton locksingletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); //三級if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}}}return singletonObject;}

createdBean

	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {if (logger.isTraceEnabled()) {logger.trace("Creating instance of bean '" + beanName + "'");}RootBeanDefinition mbdToUse = mbd;// Make sure bean class is actually resolved at this point, and// clone the bean definition in case of a dynamically resolved Class// which cannot be stored in the shared merged bean definition.Class<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// Prepare method overrides.try {mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);}try {//(即使AOP的BeanPostProcessor都不會珍惜這個機會) 提前給我們一個機會,去返回組件的代理對象。 Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.//AOP核心流程Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}try { //Spring真正自己創(chuàng)建對象Object beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean '" + beanName + "'");}return beanInstance;}catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {// A previously detected exception with proper bean creation context already,// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.throw ex;}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);}}

實例化的前置處理

	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean = null;if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {Class<?> targetType = determineTargetType(beanName, mbd);if (targetType != null) {bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);if (bean != null) {bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}mbd.beforeInstantiationResolved = (bean != null);}return bean;}

這個方法核心就在于 applyBeanPostProcessorsBeforeInstantiation() 和 applyBeanPostProcessorsAfterInitialization() 兩個方法,before 為實例化前的后處理器應(yīng)用,after 為實例化后的后處理器應(yīng)用,由于本文的主題是創(chuàng)建 bean,關(guān)于 Bean 的增強處理后也就是AOP 單獨開一篇講解。

創(chuàng)建Bean

	protected Object  doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) { //是否單例的instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {//創(chuàng)建Bean的實例,默認使用無參構(gòu)造器創(chuàng)建的對象,組件的原始對象就創(chuàng)建了instanceWrapper = createBeanInstance(beanName, mbd, args);}Object bean = instanceWrapper.getWrappedInstance();Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}//允許 后置處理器 再來修改下beanDefinition;MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition;;   Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}}// 提前暴露單實例。專門來解決循環(huán)引用問題;Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isTraceEnabled()) {logger.trace("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); //三級緩存中的Bean也會被后置處理來增強,}// Initialize the bean instance.Object exposedObject = bean;try {populateBean(beanName, mbd, instanceWrapper); //給創(chuàng)建好的對象每個屬性進行賦值,@Autowired發(fā)生在這里 數(shù)據(jù)填充exposedObject = initializeBean(beanName, exposedObject, mbd);//初始化bean}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}//早期單實例暴露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);}}if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");}}}}// Register bean as disposable.try {registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;}

大概流程如下:
createBeanInstance() 實例化 bean
populateBean() 屬性填充
循環(huán)依賴的處理
initializeBean() 初始化 bean

createBeanInstance

	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {//獲取Bean的類型  Make sure bean class is actually resolved at this point.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());}//定義Bean的示例提供者Supplier<?> instanceSupplier = mbd.getInstanceSupplier();if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);}//@Bean等可能會調(diào)用此方法進行創(chuàng)建出來if (mbd.getFactoryMethodName() != null) {return instantiateUsingFactoryMethod(beanName, mbd, args);}//快速創(chuàng)建? Shortcut when re-creating the same bean...boolean resolved = false;boolean autowireNecessary = false;if (args == null) {synchronized (mbd.constructorArgumentLock) {if (mbd.resolvedConstructorOrFactoryMethod != null) {resolved = true;autowireNecessary = mbd.constructorArgumentsResolved;}}}if (resolved) {if (autowireNecessary) {return autowireConstructor(beanName, mbd, null, null);}else {return instantiateBean(beanName, mbd);}}//后置處理器有機會在這里決定當(dāng)前bean用哪個構(gòu)造器?SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors()   Candidate constructors for autowiring?Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args); //構(gòu)造器方式的自動注入與對象創(chuàng)建}//使用默認的自己設(shè)置的高優(yōu)先級的構(gòu)造器  Preferred constructors for default construction?ctors = mbd.getPreferredConstructors();if (ctors != null) {return autowireConstructor(beanName, mbd, ctors, null);}// 默認使用無參構(gòu)造器為當(dāng)前組件創(chuàng)建對象;No special handling: simply use no-arg constructor.return instantiateBean(beanName, mbd);}

實例化策略

	protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {try {Object beanInstance;if (System.getSecurityManager() != null) {beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),getAccessControlContext());}else {beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);}BeanWrapper bw = new BeanWrapperImpl(beanInstance);initBeanWrapper(bw);return bw;}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);}}

具體在實例化的時候,并沒有直接利用反射進行創(chuàng)建對象,而是通過不同的方式,比如Cglib或者Spring的工具類進行反射的。

請?zhí)砑訄D片描述
至此,整個bean的初始化和創(chuàng)建過程就完成了。

其實整體上來說,就是先創(chuàng)建BeanFacotry,然后在創(chuàng)建Bean對象,但是Bean對象因為有AOP、事務(wù)等功能處理,所以就有很多的前后處理器進行增強對象。

http://m.aloenet.com.cn/news/30582.html

相關(guān)文章:

  • 視頻網(wǎng)站seo實戰(zhàn)免費私人網(wǎng)站建設(shè)軟件
  • 中山建設(shè)監(jiān)理有限公司 網(wǎng)站如何提高網(wǎng)站的搜索排名
  • wordpress上傳函數(shù)四川seo哪里有
  • 很好用的炫酷WordPress主題上海seo顧問
  • dede新聞網(wǎng)站源碼營銷課程培訓(xùn)視頻
  • 晉州做網(wǎng)站響應(yīng)式模版移動優(yōu)化
  • 建材公司網(wǎng)站建設(shè)方案點擊器 百度網(wǎng)盤
  • 深圳官方網(wǎng)站設(shè)計長沙網(wǎng)站策劃
  • 太原營銷網(wǎng)站建設(shè)制作平臺網(wǎng)站監(jiān)測
  • 學(xué)網(wǎng)站開發(fā)培訓(xùn)班seo為什么要進行外部優(yōu)化
  • 網(wǎng)站建設(shè)源代碼上傳百度網(wǎng)頁怎么制作
  • 企業(yè)網(wǎng)站制作簡介bt螞蟻
  • 深圳網(wǎng)絡(luò)公司做網(wǎng)站臺州網(wǎng)站seo
  • 一對一直播軟件開發(fā)夫唯老師seo
  • 購物網(wǎng)站最重要的功能我要登錄百度
  • 保定哪做網(wǎng)站好企業(yè)查詢信息平臺
  • 做網(wǎng)站切圖網(wǎng)址怎么申請注冊
  • 黃山做網(wǎng)站公司關(guān)鍵詞搜索神器
  • 建網(wǎng)站比較靠譜的公司新媒體營銷推廣方案
  • 泰安網(wǎng)站制作服務(wù)2000元代理微信朋友圈廣告
  • 更改wordpress主題百度關(guān)鍵詞優(yōu)化多久上首頁
  • 專門做二手書網(wǎng)站或app百度云搜索引擎入口網(wǎng)盤搜索神器
  • 國外做燈的網(wǎng)站市場推廣方案
  • 怎么引導(dǎo)做淘寶的客戶做官方網(wǎng)站唐山seo排名優(yōu)化
  • 做畢業(yè)設(shè)計網(wǎng)站的步驟怎么把網(wǎng)站排名排上去
  • 網(wǎng)站維護包括深圳企業(yè)網(wǎng)站制作公司
  • 全國互聯(lián)網(wǎng)安全管理服務(wù)平臺seo免費推廣軟件
  • 社交媒體 網(wǎng)站網(wǎng)址seo關(guān)鍵詞
  • 福安網(wǎng)站定制怎么樣推廣自己的店鋪和產(chǎn)品
  • 外國電商設(shè)計網(wǎng)站有哪些品牌策劃設(shè)計