日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
關(guān)于AOP,大概就到這了吧!

哈嘍,大家好,我是了不起。

創(chuàng)新互聯(lián)建站專注于網(wǎng)站建設|成都網(wǎng)站維護|優(yōu)化|托管以及網(wǎng)絡推廣,積累了大量的網(wǎng)站設計與制作經(jīng)驗,為許多企業(yè)提供了網(wǎng)站定制設計服務,案例作品覆蓋成都崗亭等行業(yè)。能根據(jù)企業(yè)所處的行業(yè)與銷售的產(chǎn)品,結(jié)合品牌形象的塑造,量身建設品質(zhì)網(wǎng)站。

今天我們繼續(xù)看看AOP相關(guān)的知識,前面說到了Javassit,Spring AOP,通過該篇,讓你對AOP有更完整的認識。

AOP

再看AOP,這是一種面向切面編程思想,相比面向?qū)ο缶幊?,可以說是站在更改維度關(guān)注對象,我們知道,對象包含由屬性和行為。 基于AOP,我們可以把一段代碼插入到對象中形成新的對象,這是織入的過程,目的是將公共的內(nèi)容寫入到業(yè)務代碼中,通過配置或簡單的編碼完成整個過程。 這樣一來不用修改原有的業(yè)務代碼,同時又能自由完成目標代碼的增強,按照代碼的設計思想,確實是降低業(yè)務與功能的耦合。

大部分框架都是為我們提供切面織入目標過程的封裝。

實現(xiàn)

通過該圖可以看到AOP相關(guān)的實現(xiàn)主要包括ASM、Cglib、JDK Proxy、AspectJ、Javassit,這些實現(xiàn)主要都是對字節(jié)碼直接操作,只不過對目標對象的增強可以發(fā)生在編譯時、編譯后或運行時。

關(guān)于AOP我們說的比較多的就是代理,這屬于設計模式的一種,但是AOP真正做的不僅僅是對目標的代理,更多的是修改,像我們常用的代理工具Cglib、JDK Proxy,都是基于面向?qū)ο蟮奶匦?,生成新?目標對象,通過繼承與代理模式來實現(xiàn)最終的增強效果。

在Java中,大部分情況下都是對方法的增強,比如Spring AOP,這樣可以解決幾乎所有的業(yè)務問題;當然切點不局限于類方法,還可以包括字段、方法、構(gòu)造函數(shù)、靜態(tài)初始值等,比如AspectJ,只不過需要特定的 編譯器來實現(xiàn)。

下面我們看下剩下的幾項實現(xiàn)AOP的技術(shù),前面說到,Spring AOP主要基于Cglib、JDK Proxy,在運行時實現(xiàn)目標對象的代理。但是Spring中卻引入了aspectj相關(guān)的依賴,但沒有用到AspectJ編譯器

JDK Proxy

JDK動態(tài)代理,主要是基于目標接口,通過ByteArrayOutputStream直接構(gòu)建字節(jié)數(shù)組,最終生成代理接口的實現(xiàn)類,基于InvocationHandler實現(xiàn)代碼的擴展與增強,通過反射來調(diào)用目標代碼的調(diào)用。

  1. 目標接口
public interface HelloService {

String hello(String name);

}
  1. 目標實現(xiàn)類
@Slf4j
public class HelloServiceImpl implements HelloService{

@Override
public String hello(String name) {
log.info("+++ 執(zhí)行方法:hello");
return String.format("hello, %s", name);
}
}
  1. 代理工廠
public class JdkProxyFactory {

public static T create(Class targetClass, InvocationHandler invocationHandler){
return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{targetClass}, invocationHandler);
}

@Slf4j
public static class LogInvocationHandler implements InvocationHandler{

private Object target;

public LogInvocationHandler(Object target) {
this.target = target;
}

/**
*
* @param proxy
* @param method
* @param args
*
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
log.info(">>> before");
Object result = method.invoke(target, args); // 執(zhí)行被代理方法
log.info(">>> afterReturning : {}", result);
return result;
} catch (Throwable e) {
log.info(">>> afterThrowing : {}", e.getMessage());
throw e;
} finally {
log.info(">>> after");
}
}
}

}
  1. 執(zhí)行測試
public class JdkProxyTests {

@Test
public void testJdkProxy(){
HelloService helloService = JdkProxyFactory.create(HelloService.class, new JdkProxyFactory.LogInvocationHandler(new HelloServiceImpl()));
helloService.hello("JDK Proxy");
}

}

Cglib

Cglib基于目標類來實現(xiàn)代理,已目標類為參考基于ASM直接操作字節(jié)碼,構(gòu)造目標對象的子類行,基于MethodInterceptor接口實現(xiàn)目標代碼的增強,通過父類調(diào)用來執(zhí)行原目標代碼,因此在執(zhí)行效率上會高于JDK動態(tài)代理。

  1. 添加依賴

cglib
cglib
3.3.0
  1. 目標類
@Slf4j
public class HiService {

public String hi(String name){
log.info("+++ 執(zhí)行方法:hi");
return String.format("hi, %s", name);
}
}
  1. 代理工廠
public class CglibFactory{

/**
*
* @param targetClass
* @param methodInterceptor
* @return
* @param
*/
public static T create(Class targetClass, MethodInterceptor methodInterceptor){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(targetClass);
enhancer.setCallback(methodInterceptor);
return (T) enhancer.create();
}

@Slf4j
public static class LogMethodInterceptor implements MethodInterceptor {

/**
*
* @param target 目標對象
* @param method 目標方法
* @param args 參數(shù)
* @param methodProxy 代理方法,注意執(zhí)行方式 methodProxy.invokeSuper
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
try {
log.info(">>> before");
Object result = methodProxy.invokeSuper(target, args); // 執(zhí)行被代理方法
log.info(">>> afterReturning : {}", result);
return result;
} catch (Throwable e) {
log.info(">>> afterThrowing : {}", e.getMessage());
throw e;
} finally {
log.info(">>> after");
}
}
}
}
  1. 執(zhí)行測試
public class CglibTests {

/**
*
*/
@Test
public void testCglib(){
HiService hiService = CglibFactory.create(HiService.class, new CglibFactory.LogMethodInterceptor());
hiService.hi("Cglib");
}

}

AspectJ

AspectJ是一個功能強大的面向切面編程框架,是對Java面向?qū)ο蟮臄U展,支持編譯時、編譯后、加載時為目標對象(不僅僅是類方法)織入代理。

切面織入時機:

  • 編譯期織入(compiler-time weaving):在類進行編譯的時候就將相應的代碼織入到元類文件的.class文件中
  • 編譯后織入(post-compiler weaving):在類編譯后,再將相關(guān)的代碼織入到.class文件中
  • 加載時織入(load-time weaving):在JVM加載.class 文件的時候?qū)⒋a織入

我們可以通過AspectJ編譯器或者maven插件aspectj-maven-plugin來實現(xiàn)。

AspectJ編譯器

  • 下載

aspectj

  • 安裝

java -jar aspectj-1.9.6.jar 配置環(huán)境變量PATH與系統(tǒng)變量CLASSPATH

  • 使用

通過下面的命令可實現(xiàn)編譯時織入的效果:

#  ajc [Options] [file... | @file... | -argfile file...]
ajc -1.8 -sourceroots .\src\main\java\ -cp %CLASS_PATH% -outjar main.jar

通過ajc編譯后并打包成main.jar,即是編譯時實現(xiàn)了目標對象的代理,通過反編譯工具可以查看到編譯后的目標對象已經(jīng)被修改。

AspectJ使用

編譯時織入(Compile-Time Weaving)

  • 編譯時織入

目標對象:

public class CTWObject {

public void run() {
System.out.println("-- Compile-Time Weaving --");
}

}

Aspect:

public aspect CTWAspect {

pointcut pc():
execution(* com.sucl.blog.aspectj.target.CTWObject.*());

before(): pc(){
System.out.println(" >> before CTW << ");
}

void around(): pc(){
System.out.println(" >> around before CTW << ");
proceed();
System.out.println(" >> around before CTW << ");
}

after(): pc(){
System.out.println(" >> after CTW << ");
}
}
  • 配置maven插件 aspectj-maven-plugin


org.codehaus.mojo
aspectj-maven-plugin
1.14.0

1.8
1.8
1.8
true
true
ignore
UTF-8




compile
test-compile



  • 執(zhí)行測試
public class AspectJCTWTests {

@Test
public void call() {
CTWObject CTWObject = new CTWObject();
CTWObject.run();
}
}

編譯后織入(Post-Compile Weaving)

  • 針對編譯好的文件,比如jar中的class文件

編寫測試的目標對象,并打包成jar文件

public class PCWObject {

public void run() {
System.out.println("-- Post-Compile Weaving --");
}

}
  • 引入上面的目標jar

com.sucls.blog
PCW-target
${project.version}
  • 配置maven插件 aspectj-maven-plugin


org.codehaus.mojo
aspectj-maven-plugin

1.11

1.8
1.8
1.8
UTF-8


com.sucls.blog
PCW-target






compile
test-compile



  • 編譯
mvn clean compile
  • 執(zhí)行測試
public class AspectJPCWTests {

@Test
public void call(){
PCWObject pcwObject = new PCWObject();
pcwObject.run();
}
}

運行時織入(Load-Time Weaving)

  • 配置VM參數(shù)
-javaagent:${project.basedir}/lib/aspectjweaver-1.9.7.jar

或者配置maven-surefire-plugin插件


org.apache.maven.plugins
maven-surefire-plugin
2.10


-javaagent:${project.basedir}/lib/aspectjweaver-1.9.7.jar

true
always

  • 配置aop.xml

/src/main/resources/META-INF/aop.xml






  • 啟動測試
public class AspectJLTWTests {

@Test
public void call(){
LTWObject LTWObject = new LTWObject();
LTWObject.run();
}
}

結(jié)束語

不管是javassit,還是jdk proxy或者cglib來實現(xiàn)AOP,都是通過對字節(jié)碼的修改,只不過對字節(jié)碼操作方式不一樣。通過上面的例子我們可以認識到各種AOP框架的使用方式。在究其原理時, 能夠能夠知道這些工具到底為我們做了什么。


網(wǎng)站欄目:關(guān)于AOP,大概就到這了吧!
網(wǎng)站路徑:http://www.5511xx.com/article/cojjehd.html