五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Spring AOP的核心應(yīng)用與原理解析

2019-09-19 15:37 作者:P8架構(gòu)師諸葛  | 我要投稿


概述

AOP(Aspect Oriented Programming) 面向切面編程,實質(zhì)上是對我們的對象進行增強,并且提供良好的管理機制。

對于對象增強,可以有以下幾種方法

?

1.? 裝飾器模式,比如JDK中的I/O流

InputStream inputStream = new LineNumberInputStream(new BufferedInputStream(new FileInputStream("")));

2.? 靜態(tài)代理模式

3.? 適配器模式

4.? 動態(tài)代理,包括 ?Proxy 和 CGLIB 等方法進行動態(tài)代理

?

SpringAOP 是一套 AOP 的解決方案,他比傳統(tǒng)的對象增強更容易管理和擴展。

在對象增強上,它的規(guī)則是:基于動態(tài)代理來實現(xiàn)。默認地,如果使用接口方法的,用 JDK 提供的動態(tài)代理實現(xiàn),如果沒有接口,使用 CGLIB 實現(xiàn)。SpringAOP 基于 IOC 容器,動態(tài)代理之后,會把原對象替換成動態(tài)代理的對象。

?

?

概念

Advisor 是 AOP 的一個概念,他是 保存AOP配置 的一個單位

?

·????? Advice:方法攔截邏輯,可控制該方法執(zhí)行前和方法執(zhí)行后或者出現(xiàn)異常時候的執(zhí)行的邏輯

·????? PointCut: 在哪些地方的方法應(yīng)用攔截

·????? Advisor里面有且只有一個 Advice,可以對多個 PointCut 執(zhí)行 Advice 方法。

?


?

注解配置 Spring AOP

?

SpringAOP 和 AspectJ 沒多大關(guān)系,而僅僅是使用了 AspectJ 中的概念,包括使用的注解也是直接來自于 AspectJ 的包(有點迷)。

?

依賴

<dependency>

??? <groupId>org.aspectj</groupId>

??? <artifactId>aspectjweaver</artifactId>

??? <version>1.8.11</version>

</dependency>

或者在 SpringBoot

<dependency>

?? <groupId>org.springframework.boot</groupId>

?? <artifactId>spring-boot-starter-aop</artifactId>

</dependency>

?

注解

注解開啟,在Main 類上面標上這個注解

@EnableAspectJAutoProxy

?

在 配置文件Bean 上 打上 @Aspect

@Aspect

?

配置 PointCut

@Aspect

public class SystemArchitecture {

??? @Pointcut("execution(* transfer(..))")// the pointcut expression

??? private void anyOldTransfer() {}// the pointcut signature

}

?

一些配置規(guī)則

@Pointcut("execution(* transfer(..))")

// 方法簽名

@Pointcut("within(com.javadoop.springaoplearning.service..*)")

// 包下所有類的所有方法

@Pointcut("execution( .*(..))

@annotation(com.javadoop.annotation.Subscribe)")

// 指定注解的所有方法

@Pointcut("bean(*Service)")

// 指定 bean 名的所有方法

// 通常 "." 代表一個包名,".." 代表包及其子包,方法參數(shù)任意匹配使用兩個點 ".."

?

?

一些實踐中的配置

@Aspect

public class SystemArchitecture {

?

??? // web 層

??? @Pointcut("within(com.javadoop.web..*)")

??? public void inWebLayer() {}

?

??? // service 層

??? @Pointcut("within(com.javadoop.service..*)")

??? public void inServiceLayer() {}

?

??? // dao 層

??? @Pointcut("within(com.javadoop.dao..*)")

??? public void inDataAccessLayer() {}

?

??? // service 實現(xiàn),注意這里指的是方法實現(xiàn),其實通常也可以使用 bean(*ServiceImpl)

??? @Pointcut("execution(* com.javadoop..service.*.*(..))")

??? public void businessService() {}

?

??? // dao 實現(xiàn)

??? @Pointcut("execution(* com.javadoop.dao.*.*(..))")

??? public void dataAccessOperation() {}

}

?

配置 Advice

@Aspect

public class AdviceExample {

?

??? // 這里會用到我們前面說的 SystemArchitecture

??? // 下面方法就是寫攔截 "dao層實現(xiàn)"

??? @Before("com.javadoop.aop.SystemArchitecture.dataAccessOperation()")

??? public void doAccessCheck() {

??????? // ... 實現(xiàn)代碼

??? }

?

??? @Before("com.javadoop.springaoplearning.aop_spring_2_aspectj.SystemArchitecture.businessService()")

??? public void logArgs(JoinPoint joinPoint) {

??????? System.out.println("方法執(zhí)行前,打印入?yún)ⅲ?#34; + Arrays.toString(joinPoint.getArgs()));

??? }

?

??? @AfterReturning("com.javadoop.aop.SystemArchitecture.dataAccessOperation()")

??? public void doAccessCheck() {

??????? // ...

??? }

?

??? @AfterReturning(

??????? pointcut="com.javadoop.aop.SystemArchitecture.dataAccessOperation()",

??????? returning="retVal")

??? public void doAccessCheck(Object retVal) {

??????? // 這樣,進來這個方法的處理時候,retVal 就是相應(yīng)方法的返回值,是不是非常方便

??????? //? ... 實現(xiàn)代碼

??? }

?

??? // 異常返回

??? @AfterThrowing("com.javadoop.aop.SystemArchitecture.dataAccessOperation()")

??? public void doRecoveryActions() {

??????? // ... 實現(xiàn)代碼

??? }

?

??? @AfterThrowing(

??????? pointcut="com.javadoop.aop.SystemArchitecture.dataAccessOperation()",

??????? throwing="ex")

??? public void doRecoveryActions(DataAccessException ex) {

??????? // ... 實現(xiàn)代碼

??? }

?

??? // 注意理解它和 @AfterReturning 之間的區(qū)別,這里會攔截正常返回和異常的情況

??? @After("com.javadoop.aop.SystemArchitecture.dataAccessOperation()")

??? public void doReleaseLock() {

??????? // 通常就像 finally 塊一樣使用,用來釋放資源。

??????? // 無論正常返回還是異常退出,都會被攔截到

??? }

?

??? // 感覺這個很有用吧,既能做 @Before 的事情,也可以做 @AfterReturning 的事情

??? @Around("com.javadoop.aop.SystemArchitecture.businessService()")

??? public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {

??????? // start stopwatch

??????? Object retVal = pjp.proceed();

??????? // stop stopwatch

??????? return retVal;

??? }

?

}

?

advisor會由Spring給我們生成。

?

原理解析

?

在 Spring中,Bean 初始化結(jié)束后,會對每一個 bean 調(diào)用一次實現(xiàn) BeanPostProcessor 接口的 Bean postProcessAfterInitialization() ?方法。

?

當我們通過注解配置 AOP (XML差不多),Spring 會 給我們注冊一個 AnnotationAwareAspectJAutoProxyCreator 的 Bean,這個 Bean 就實現(xiàn)了 BeanPostProcessor 接口 的 postProcessAfterInitialization() 方法。

?

這個方法傳入 原始Bean,返回處理過的 Bean ,我們在這里就可以對 這個 Bean 偷梁換柱,換成 Proxy 對象。實現(xiàn)我們代理的目的。

?

在 ProxyCreater 中實現(xiàn)了這個方法:

?

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

?? if (bean != null) {

????? Object cacheKey = getCacheKey(bean.getClass(), beanName);

????? if (!this.earlyProxyReferences.contains(cacheKey)) {

???????? return wrapIfNecessary(bean, beanName, cacheKey);

????? }

?? }

?? return bean;

}

?

這個方法干了這些事情:

1.? 把這個 bean 匹配的AOP增強配置打包成 advisor

?

2.? 保存這個Bean的接口方法

3.? 根據(jù)接口方法和配置決定使用 JDK Proxy 代理生成器(JdkDynamicAopProxy) 還是 CGLIB 代理生成器(ObjenesisCglibAopProxy) 來生成代理對象,一般情況下:

a.? 如果被代理的目標類實現(xiàn)了一個或多個自定義的接口,那么就會使用 JDK 動態(tài)代理

b.? 如果沒有實現(xiàn)任何接口,會使用 CGLIB 實現(xiàn)代理。

4.? 生成代理對象后,把這個代理對象替換掉原來的 Bean

?

簡單講一下創(chuàng)建 JDK Proxy 代理,CGLIB類似,但是操縱比較復(fù)雜。

Proxy 使用方法見 Java 動態(tài)代理機制 (一) JDK Proxy 詳解

JdkDynamicAopProxy -> getProxy

public Object getProxy(ClassLoader classLoader) {

?? if (logger.isDebugEnabled()) {

????? logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());

?? }

??

?? Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);

?? findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);

?? // 獲取這個Bean的所有接口,調(diào)用 JDK 的 Proxy 生成 Proxy

?? // 第三個是? InvocationHandler,代理類實現(xiàn)了? InvocationHandler 接口,有 invoke 方法

?? return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

}

?

當我們調(diào)用 被 Proxy 代理的類的時候,都會調(diào)用到 JdkDynamicAopProxy 的 invoke 方法,invoke 方法 在我們原方法的周圍做一些增強(從advisor中獲取我們寫好的增強函數(shù))。剩下的就交給 JDK 來處理了。

?


Spring AOP的核心應(yīng)用與原理解析的評論 (共 條)

分享到微博請遵守國家法律
罗山县| 伊春市| 宜兴市| 黔西县| 宝山区| 清苑县| 洪洞县| 潮安县| 兴城市| 尼玛县| 葫芦岛市| 华坪县| 桦甸市| 澄城县| 定远县| 来安县| 关岭| 读书| 桦南县| 同心县| 资溪县| 灵宝市| 忻州市| 黑水县| 通榆县| 上犹县| 新蔡县| 赤峰市| 大足县| 开鲁县| 新建县| 陵川县| 会同县| 丹巴县| 陆良县| 历史| 时尚| 丰城市| 九龙城区| 武平县| 博湖县|