中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

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

寧波網(wǎng)站建設(shè)免費咨詢漯河網(wǎng)絡(luò)推廣哪家好

寧波網(wǎng)站建設(shè)免費咨詢,漯河網(wǎng)絡(luò)推廣哪家好,貴陽做網(wǎng)站設(shè)計,太倉有做網(wǎng)站的地方嗎?作者簡介:大家好,我是Leo,熱愛Java后端開發(fā)者,一個想要與大家共同進步的男人😉😉 🍎個人主頁:Leo的博客 💞當(dāng)前專欄: Spring專欄 ?特色專欄: M…

Springgif.gif

?作者簡介:大家好,我是Leo,熱愛Java后端開發(fā)者,一個想要與大家共同進步的男人😉😉
🍎個人主頁:Leo的博客
💞當(dāng)前專欄: Spring專欄
?特色專欄: MySQL學(xué)習(xí)
🥭本文內(nèi)容:Spring5學(xué)習(xí)筆記—AOP編程
🖥?個人小站 :個人博客,歡迎大家訪問
📚個人知識庫: 知識庫,歡迎大家訪問

1. 靜態(tài)代理設(shè)計模式

1.1 為什么需要代理設(shè)計模式

  • 在JavaEE分層開發(fā)開發(fā)中,那個層次對于我們來講最重要

    DAO ---> Service --> Controller JavaEE分層開發(fā)中,最為重要的是Service層
    
  • Service層中包含了哪些代碼?

    Service層中 = 核心功能(幾十行 上百代碼) + 額外功能(附加功能)
    1. 核心功能業(yè)務(wù)運算DAO調(diào)用
    2. 額外功能(事務(wù)、日志、性能...)1. 不屬于業(yè)務(wù)2. 可有可無3. 代碼量很小 
    
  • 額外功能書寫在Service層中好不好?

    Controller層(Service層的調(diào)用者)除了需要核心功能,還需要這些額外功能。

    但是從軟件設(shè)計者角度看:Service層最好不要寫額外功能。

  • 現(xiàn)實生活中的解決方式

    image-20230815111510825

代理模式是一種比較好理解的設(shè)計模式。簡單來說就是 我們使用代理對象來代替對真實對象(real object)的訪問,這樣就可以在不修改原目標對象的前提下,提供額外的功能操作,擴展目標對象的功能。

代理模式的主要作用是擴展目標對象的功能,比如說在目標對象的某個方法執(zhí)行前后你可以增加一些自定義的操作。

代理模式: 為一個對象提供一個替身,以控制對這個對象的訪問。即通過代理對象訪問目標對象.這樣做的好處是:可以在目標對象實現(xiàn)的基礎(chǔ)上,增強額外的功能操作,即擴展目標對象的功能。

被代理的對象可以是遠程對象、創(chuàng)建開銷大的對象或需要安全控制的對象

舉個例子:當(dāng)我們工作之后需要出去租房子,房東張貼廣告帶我看房子,最后簽合同,但是房東只想坐著簽合同并不想到處跑著看房子,于是就找了一個中介專門來宣傳廣告并且?guī)ё鈶艨捶孔?#xff0c;而房東只負責(zé)簽合同收錢!中介在這里就可以看作是代理你的代理對象代理的行為(方法)是帶租戶看房子。

img

1.2 代理設(shè)計模式分析

2.1 概念

通過代理類,為原始類(目標)增加額外的功能 好處:利于原始類(目標)的維護

2.2 名詞解釋

1. 目標類 原始類 指的是 業(yè)務(wù)類 (核心功能 --> 業(yè)務(wù)運算 DAO調(diào)用)
2. 目標方法,原始方法目標類(原始類)中的方法 就是目標方法(原始方法)
3. 額外功能 (附加功能)日志,事務(wù),性能

2.3 代理開發(fā)的核心要素

代理類 = 實現(xiàn)和目標類相同的接口 + 在同名方法中添加額外功能 + 調(diào)用原始類同名方法房東 ---> public interface UserService{m1m2}UserServiceImpl implements UserService{m1 ---> 業(yè)務(wù)運算 DAO調(diào)用m2 }UserServiceProxy implements UserServicem1m2

2.4 編碼

靜態(tài)代理:為每一個原始類,手動編寫一個代理類 (.java .class)

image-20230815112248257

2.5 靜態(tài)代理存在的問題

1. 靜態(tài)類文件數(shù)量過多,不利于項目管理UserServiceImpl  UserServiceProxyOrderServiceImpl OrderServiceProxy
2. 額外功能維護性差代理類中 額外功能修改復(fù)雜(麻煩)

2. Spring的動態(tài)代理開發(fā)

2.1 Spring動態(tài)代理的概念

概念:通過代理類為原始類(目標類)增加額外功能,代理類由Spring動態(tài)生成。
好處:利于原始類(目標類)的維護

2.2 搭建開發(fā)環(huán)境

<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.1.14.RELEASE</version>
</dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.8</version>
</dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.3</version>
</dependency>

2.3 Spring動態(tài)代理的開發(fā)步驟

1. 創(chuàng)建原始對象(目標對象)

public class UserServiceImpl implements UserService{@Overridepublic void register(User user) {System.out.println("UserServiceImpl.register");}@Overridepublic boolean login(String name, String password) {System.out.println("UserServiceImpl.login");return true;}
}
<bean id="userServiceImpl" class="com.Leo.dynamic.service.impl.UserServiceImpl"/>

2. 定義額外功能

實現(xiàn)MethodBeforeAdvice接口

public class Before implements MethodBeforeAdvice {//作用:給原始方法添加額外功能//注意:會在原始方法運行之前運行此方法@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("-----method before advice log------");}
}
<bean id="before" class="com.Leo.dynamic.service.Before"/>

3. 定義切入點

1. 切入點:額外功能加入的位置2. 目的:由程序員根據(jù)自己的需要,決定額外功能加入給那個原始方法
register()
login()簡單的測試:所有方法都做為切入點,都加入額外的功能。
<aop:config><aop:pointcut id="pc" expression="execution(* *(..))"/>
</aop:config>

4. 組裝

<!-- 組裝切入點與額外功能 -->
<aop:advisor advice-ref="before" pointcut-ref="pc"/>

5. 測試調(diào)用

目的:獲得Spring工廠創(chuàng)建的動態(tài)代理對象,并進行調(diào)用
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
注意:1. Spring的工廠通過	原始對象的id值獲得的是代理對象2. 獲得代理對象后,可以通過聲明接口類型,進行對象的存儲UserService userService=(UserService)ctx.getBean("userServiceImpl");userService.login("","");
userService.register(new User());

控制臺打印: 可以發(fā)現(xiàn)在日志之前輸入了

image-20230815114453445

2.4 動態(tài)代理細節(jié)分析

4.1 Spring創(chuàng)建的動態(tài)代理類在哪里?

Spring框架在運行時,通過動態(tài)字節(jié)碼技術(shù),在JVM創(chuàng)建的,運行在JVM內(nèi)部,等程序結(jié)束后就消失了。

什么叫動態(tài)字節(jié)碼技術(shù):通過第三方動態(tài)字節(jié)碼框架,在JVM中創(chuàng)建對應(yīng)類的字節(jié)碼,進而創(chuàng)建對象,當(dāng)虛擬機結(jié)束,動態(tài)字節(jié)碼跟著消失。

結(jié)論:動態(tài)代理不需要定義類文件,都是JVM運行過程中動態(tài)創(chuàng)建的,所以不會造成靜態(tài)代理,類文件數(shù)量過多,影響項目管理的問題。

image-20200423165547079

4.2 動態(tài)代理編程簡化代理的開發(fā)

在額外功能不改變的前提下,創(chuàng)建其他目標類(原始類)的代理對象時,只需要指定原始(目標)對象即可。

3. Spring動態(tài)代理詳解

3.1 額外功能的詳解

  • MethodBeforeAdvice分析

    作用:原始方法執(zhí)行之前,運行額外功能。

    public class Before implements MethodBeforeAdvice {/*** 作用:給原始方法添加額外功能* 注意:會在原始方法運行之前運行此方法* @param method 原始方法 login() register() ...* @param objects 原始方法的參數(shù)列表 name password ...* @param o 原始對象 UserServiceImpl OrderServiceImpl* @throws Throwable 拋出的異常*/@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {System.out.println("---- MethodBeforeAdvice  log... ----");}
    }
    

實戰(zhàn):需要時才用,可能都會用到,也有可能都不用。

  • MethodInterceptor(方法攔截器)

    MethodInterceptor接口:額外功能可定義在原始方法執(zhí)行 前、后、前和后。

    public class Around implements MethodInterceptor {/*** @param invocation 封裝了原始方法 invocation.proceed()表示原始方法的運行* @return 原始方法的返回值* @throws Throwable 可能拋出的異常*/@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("------ 額外功能 log -----");//原始方法的執(zhí)行Object ret = invocation.proceed();//返回原始方法的返回值return ret;}
    }
    

額外功能運行在原始方法執(zhí)行之后

  public Object invoke(MethodInvocation invocation) throws Throwable {Object ret = invocation.proceed();System.out.println("-----額外功能運行在原始方法執(zhí)行之后----");return ret;}

額外功能運行在原始方法執(zhí)行之前和之后(實戰(zhàn):事務(wù)需要在之前和之后都運行)

@Override
public Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("-----額外功能運行在原始方法執(zhí)行之前----");Object ret = invocation.proceed();System.out.println("-----額外功能運行在原始方法執(zhí)行之后----");return ret;
}

額外功能運行在原始方法拋出異常時

  @Override
public Object invoke(MethodInvocation invocation) throws Throwable {Object ret = null;try {ret = invocation.proceed();} catch (Throwable throwable) {System.out.println("-----原始方法拋出異常 執(zhí)行的額外功能 ---- ");throwable.printStackTrace();}return ret;}

MethodInterceptor可以影響原始方法的返回值

@Override
public Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("------log-----");Object ret = invocation.proceed();//拿到原始方法的返回值后進行一些操作就會影響,直接返回就不影響return false;
}

3.2 切入點詳解

切入點決定了額外功能加入的位置。

<aop:pointcut id="pc" expression="execution(* *(..))"/>
exection(* *(..)) ---> 匹配了所有方法    a  b  c 1. execution()  切入點函數(shù)
2. * *(..)      切入點表達式 

1. 切入點表達式

  • 方法切入點表達式:

    image-20200425105040237

    *  *(..)  --> 所有方法* ---> 修飾符 返回值
    * ---> 方法名
    ()---> 參數(shù)表
    ..---> 對于參數(shù)沒有要求 (0個或多個)
    

舉例:

  # 定義login方法作為切入點* login(..)# 定義register作為切入點* register(..)# 定義名字為login且有兩個字符串類型參數(shù)的方法 作為切入點* login(String,String)# 注意:非java.lang包中的類型,必須要寫全限定名* register(com.Leo.proxy.User)# ..可以和具體的參數(shù)類型連用(至少有一個參數(shù)是String類型)* login(String,..)# 精準方法切入點限定# 修飾符 返回值    包.類.方法(參數(shù))*             com.yuziayn.proxy.UserServiceImpl.login(..)*             com.Leo.proxy.UserServiceImpl.login(String,String)
  • 類切入點表達式:

    指定特定的類作為切入點,即這個類中所有的方法都會加上額外功能。

    舉例:

    # 類中的所有方法都加入額外功能 
    * com.Leo.proxy.UserServiceImpl.*(..)# 忽略包
    # 1. 類只在一級包下  com.UserServiceImpl
    * *.UserServiceImpl.*(..)# 2. 類可在多級包下  com.Leo.proxy.UserServiceImpl
    * *..UserServiceImpl.*(..)
    
  • 包切入點表達式:

    指定包作為切入點,即這個包中的所有類及其方法都會加入額外的功能。

    舉例:

    # proxy包作為切入點,即proxy包下所有類中的所有方法都會加入額外功能,但是不包括其子包中的類!
    * com.Leo.proxy.*.*(..)# 當(dāng)前包及其子包都生效
    * com.Leo.proxy..*.*(..) 
    

2 切入點函數(shù)

作用:用于執(zhí)行切入點表達式。

  1. execution()

    最為重要的切入點函數(shù),功能最全!
    用于執(zhí)行:方法切入點表達式、類切入點表達式、包切入點表達式 弊端:execution執(zhí)行切入點表達式 ,書寫麻煩execution(* com.Leo.proxy..*.*(..))注意:其他的切入點函數(shù) 只是簡化execution書寫復(fù)雜度,功能上完全一致
    
  2. args()

    # 作用:用于函數(shù)(方法)參數(shù)的匹配# 舉例:方法參數(shù)必須得是2個字符串類型的參數(shù)execution(* *(String,String))等價于:args(String,String)
    
  3. within()

    # 作用:用于進行類、包切入點表達式的匹配
    # 舉例:
    # UserServiceImpl類作為切入點:execution(* *..UserServiceImpl.*(..))within(*..UserServiceImpl)
    # proxy包作為切入點:execution(* com.Leo.proxy..*.*(..))within(com.yuziayan.proxy..*)
    
  4. @annotation()

    <!-- 作用:為具有特殊注解的方法加入額外功能 --><aop:pointcut id="" expression="@annotation(com.baizhiedu.Log)"/>
    
  5. 切入點函數(shù)間的邏輯運算:

    目的:整合多個切入點函數(shù)一起配合工作,進而完成更為復(fù)雜的需求。

    • and 與操作(同時滿足)

      # 案例:方法名為login,同時有2個字符串類型的參數(shù):execution(* login(String,String))execution(* login(..)) and args(String,String)# 注意:與操作不能用于同種類型的切入點函數(shù) 
      # 錯誤案例:register方法 和 login方法作為切入點(不能用and,而用or!)execution(* login(..)) and execution(* register(..))
      # 上面的語句會發(fā)生錯誤,因為其實際表達的含義是方法名為login同時方法名為register,顯然有悖邏輯,此時應(yīng)該用到的是 or
      
  • or 或操作(滿足一種即可)

       # 案例:register方法 和 login方法作為切入點 execution(* login(..)) or  execution(* register(..))
    

4. AOP編程

4.1 AOP概念

# AOP (Aspect Oriented Programing)   面向切面編程 = Spring動態(tài)代理開發(fā)
# 以切面為基本單位的程序開發(fā),通過切面間的彼此協(xié)同,相互調(diào)用,完成程序的構(gòu)建
# 切面 = 切入點 + 額外功能# OOP (Object Oriented Programing)   面向?qū)ο缶幊?Java
# 以對象為基本單位的程序開發(fā),通過對象間的彼此協(xié)同,相互調(diào)用,完成程序的構(gòu)建# POP (Procedure Oriented Programing) 面向過程(方法、函數(shù))編程 C 
# 以過程為基本單位的程序開發(fā),通過過程間的彼此協(xié)同,相互調(diào)用,完成程序的構(gòu)建# AOP的概念:本質(zhì)就是Spring的動態(tài)代理開發(fā),通過代理類為原始類增加額外功能。好處:利于原始類的維護
# 注意:AOP編程不可能取代OOP,而是OOP編程的補充。

4.2 AOP編程的開發(fā)步驟

  1. 原始對象
  2. 額外功能 (MethodInterceptor)
  3. 切入點
  4. 組裝切面 (額外功能+切入點)

4.3 切面的名詞解釋

切面 = 切入點 + 額外功能 幾何學(xué)面 = 點 + 相同的性質(zhì)

image-20230529150312064

5. AOP的底層實現(xiàn)原理

5.1 核心問題

  • AOP如何創(chuàng)建動態(tài)代理類?(動態(tài)字節(jié)碼技術(shù))
  • Spring工廠如何加工創(chuàng)建代理對象?通過原始對象的id值,獲得的是代理對象。

5.2 動態(tài)代理類的創(chuàng)建

1. JDK的動態(tài)代理

  • Proxy.newProxyInstance()方法參數(shù)詳解:

    image-20200428175248912

image-20200428175316276

  • 編碼:

    public class TestJDKProxy {public static void main(String[] args) {//1.創(chuàng)建原始對象//注意:由于后面匿名子類的方法中用到了userService,所以應(yīng)該用final修飾//     而JDK1.8以后默認加了final,不需要手動加UserService userService = new UserServiceImpl();//2.JDK創(chuàng)建代理對象InvocationHandler handler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("----------- JDKProxy log -----------");\//目標方法運行:Object ret = method.invoke(userService, args);return ret;}};UserService userServiceProxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(),handler);userServiceProxy.login("Leo", "123456");userServiceProxy.register(new User());}
    }
    

2. CGlib的動態(tài)代理

  • 原理:通過父子繼承關(guān)系創(chuàng)建代理對象。原始類作為父類,代理類作為子類,這樣既可以保證2者方法一致,同時在代理類中提供新的實現(xiàn)(額外功能+原始方法)

image-20200429111709226

  • CGlib編碼:

    package com.Leo.cglib;import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class TestCGlibProxy {public static void main(String[] args) {//1.創(chuàng)建原始對象UserServiceImpl userService = new UserServiceImpl();//2.通過CGlib創(chuàng)建代理對象//  2.1 創(chuàng)建EnhancerEnhancer enhancer = new Enhancer();//  2.2 設(shè)置借用類加載器enhancer.setClassLoader(TestCGlibProxy.class.getClassLoader());//  2.3 設(shè)置父類(目標類)enhancer.setSuperclass(userService.getClass());//  2.4 設(shè)置回調(diào),額外功能寫在里面enhancer.setCallback(new MethodInterceptor() {//相當(dāng)于 InvocationHandler --> invoke()@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {//額外功能:System.out.println("========= CGlibProxy log ========");//目標方法執(zhí)行:Object ret = method.invoke(userService, objects);return ret;}});//  2.5 通過Enhancer對象創(chuàng)建代理UserServiceImpl service = (UserServiceImpl) enhancer.create();//測試:service.register();service.login();}
    }
    

3. 總結(jié)

1. JDK動態(tài)代理   Proxy.newProxyInstance()  
# 通過目標類實現(xiàn)的接口創(chuàng)建代理類 
2. Cglib動態(tài)代理 Enhancer                  
# 通過繼承目標類創(chuàng)建代理類 

5.3 Spring工廠如何返回代理對象

  • 思路分析:

image-20200430113353205

  • 編碼模擬:

    public class ProxyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {InvocationHandler invocation = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("----------- 模擬Spring返回代理對象的方式 log -----------");Object ret = method.invoke(bean, args);return ret;}};return Proxy.newProxyInstance(ProxyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), invocation);}
    }
    
      <!-- 1.配置原始對象 --><bean id="userService" class="com.Leo.factory.UserServiceImpl"></bean><!-- 2.配置自己模擬的ProxyBeanPostProcessor --><bean id="proxyBeanPostProcessor" class="com.Leo.factory.ProxyBeanPostProcessor"/>
    

6. 基于注解的AOP編程

6.1 開發(fā)步驟:

  1. 原始對象

  2. 額外功能

  3. 切入點

  4. 組裝切面

    /*** 聲明切面類     @Aspect* 定義額外功能   @Around* 定義切入點     @Around("execution(* login(..))")**/
    @Aspect
    public class MyAspect {@Around("execution(* login(..))")//組裝了切入點和額外功能public Object around(ProceedingJoinPoint joinPoint) throws Throwable {//額外功能:System.out.println("--------- 基于注解的AOP編程 log --------");//原始方法執(zhí)行:Object ret = joinPoint.proceed();return ret;}
    }
    
       <!-- 原始對象 --><bean id="userService" class="com.Leo.aspect.UserServiceImpl"></bean><!-- 切面 --><bean id="myAspect" class="com.Leo.aspect.MyAspect"/><!-- 開啟基于注解的AOP編程 --><aop:aspectj-autoproxy/>
    

6.2 細節(jié)分析:

  • 切入點復(fù)用:

    @Aspect
    public class MyAspect {/*** 切入點復(fù)用:定義一個函數(shù),加上@Pointcut注解,通過該注解的value定義切入點表達式,以后可以復(fù)用。*/@Pointcut("execution(* login(..))")public void myPointcut(){}@Around("myPointcut()")//組裝了切入點和額外功能public Object around(ProceedingJoinPoint joinPoint) throws Throwable {//額外功能:System.out.println("--------- 基于注解的AOP編程 log --------");//原始方法執(zhí)行:Object ret = joinPoint.proceed();return ret;}@Around("myPointcut()")public Object around1(ProceedingJoinPoint joinPoint) throws Throwable {//額外功能:System.out.println("--------- 基于注解的AOP編程 tx --------");//原始方法執(zhí)行:Object ret = joinPoint.proceed();return ret;}}
    
  • 動態(tài)代理的創(chuàng)建方式:

    AOP底層實現(xiàn)  2種代理創(chuàng)建方式1.  JDK   通過實現(xiàn)接口,創(chuàng)建代理對象2.  Cglib 通過繼承目標類,創(chuàng)建代理對象默認情況 AOP編程 底層應(yīng)用JDK動態(tài)代理創(chuàng)建方式 如果要切換Cglib1. 基于注解AOP開發(fā)<aop:aspectj-autoproxy proxy-target-class="true" />2. 傳統(tǒng)的AOP開發(fā)<aop:config proxy-target-class="true"></aop>
    

7. AOP開發(fā)中的一個坑

坑:在同一個業(yè)務(wù)類中,業(yè)務(wù)方法間相互調(diào)用時,只有最外層的方法,加入了額外功能(內(nèi)部的方法,通過普通的方式調(diào)用,運行的都是原始方法)。如果想讓內(nèi)層的方法也調(diào)用代理對象的方法,就要實現(xiàn)AppicationContextAware獲得工廠,進而獲得代理對象。

public class UserServiceImpl implements UserService, ApplicationContextAware {private ApplicationContext ctx;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.ctx = applicationContext;}@Log@Overridepublic void register(User user) {System.out.println("UserServiceImpl.register 業(yè)務(wù)運算 + DAO ");//throw new RuntimeException("測試異常");//調(diào)用的是原始對象的login方法 ---> 核心功能/*設(shè)計目的:代理對象的login方法 --->  額外功能+核心功能ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext2.xml");UserService userService = (UserService) ctx.getBean("userService");userService.login();Spring工廠重量級資源 一個應(yīng)用中 應(yīng)該只創(chuàng)建一個工廠*/UserService userService = (UserService) ctx.getBean("userService");userService.login("Leo", "123456");}@Overridepublic boolean login(String name, String password) {System.out.println("UserServiceImpl.login");return true;}
}

8. AOP階段知識總結(jié)

AOP 總結(jié)

http://www.risenshineclean.com/news/1179.html

相關(guān)文章:

  • 微信微網(wǎng)站平臺seo優(yōu)化流程
  • j昆明網(wǎng)站制作公司關(guān)鍵詞搜索指數(shù)
  • 怎么靠做網(wǎng)站賺錢嗎企業(yè)宣傳方式有哪些
  • python 做網(wǎng)站開發(fā)嗎app拉新怎么做
  • 銅山區(qū)建設(shè)局局網(wǎng)站周保春安卓優(yōu)化大師舊版
  • 網(wǎng)站搜索不到公司網(wǎng)站如何建造一個網(wǎng)站
  • 網(wǎng)址你知道我的意思的免費何鵬seo
  • 做網(wǎng)站的服務(wù)商最新軍事新聞今日最新消息
  • 誰可以做網(wǎng)站優(yōu)化排名推廣百度管理員聯(lián)系方式
  • 讓其他公司做網(wǎng)站應(yīng)注意什么問題網(wǎng)站搜索引擎優(yōu)化主要方法
  • 溫州網(wǎng)站推廣哪家好國家免費技能培訓(xùn)
  • 東莞南城網(wǎng)站建設(shè)價格站內(nèi)關(guān)鍵詞自然排名優(yōu)化
  • 湖南做網(wǎng)站磐石網(wǎng)絡(luò)案例哈爾濱百度關(guān)鍵詞優(yōu)化
  • 400電話網(wǎng)站源碼百度集團總部在哪里
  • 做電影網(wǎng)站還是國外服務(wù)器如何做一個營銷方案
  • 珠海營銷型網(wǎng)站建設(shè)公司長沙網(wǎng)站優(yōu)化推廣方案
  • 澄邁網(wǎng)站新聞建設(shè)百度空間登錄
  • 制作網(wǎng)站公司 可以要求后續(xù)修改嗎查詢網(wǎng)站注冊信息
  • 直裝模板源碼搜索引擎優(yōu)化自然排名的優(yōu)點
  • 成都建設(shè)銀行社會招聘網(wǎng)站今日熱點新聞大事件
  • 用dw制作個介紹家鄉(xiāng)網(wǎng)站煙臺網(wǎng)站建設(shè)
  • 做網(wǎng)站賺錢嗎?pageadmin建站系統(tǒng)
  • 免費建站網(wǎng)站網(wǎng)站開發(fā)需要的技術(shù)
  • 制作百度移動網(wǎng)站每日一則新聞?wù)?/a>
  • 慈利做網(wǎng)站在哪里sem和seo有什么區(qū)別
  • 微信手機網(wǎng)站開發(fā)外貿(mào)網(wǎng)站外鏈平臺
  • 蘋果電腦做網(wǎng)站的步驟seo課程培訓(xùn)中心
  • 手機移動網(wǎng)絡(luò)限制網(wǎng)站武漢電腦培訓(xùn)學(xué)校有哪些
  • 鄉(xiāng)鎮(zhèn)網(wǎng)站建設(shè)工作計劃國際新聞最新消息
  • wordpress mysql 配置關(guān)鍵詞優(yōu)化難度查詢