使用自定義注解和@Aspect實現(xiàn)責(zé)任鏈模式的組件增強的詳細代碼
責(zé)任鏈模式
責(zé)任鏈模式是一種行為設(shè)計模式,其作用是將請求的發(fā)送者和接收者解耦,從而可以靈活地組織和處理請求。它通過將請求沿著一個由多個處理器組成的鏈路進行傳遞和處理,直到有一個處理器能夠處理該請求或者鏈路的末端。
該模式的主要作用是:
解耦請求發(fā)送者和接收者:責(zé)任鏈模式將發(fā)送者和接收者解耦,發(fā)送者無需知道具體是哪個接收者來處理請求,接收者也無需知道請求的發(fā)送者是誰,從而提高系統(tǒng)的靈活性和可維護性。
動態(tài)組織和處理請求:責(zé)任鏈模式可以動態(tài)地組織和處理請求,可以根據(jù)實際情況靈活地調(diào)整鏈路上的處理器順序和數(shù)量,實現(xiàn)不同的業(yè)務(wù)邏輯和處理策略。
避免請求的硬編碼:責(zé)任鏈模式通過配置和鏈路的方式來處理請求,避免了請求的硬編碼,使得系統(tǒng)更易于擴展和維護。
應(yīng)用場景:
請求的處理涉及多個環(huán)節(jié)或多個對象:當(dāng)一個請求需要經(jīng)過多個處理環(huán)節(jié)或者多個對象來處理時,可以使用責(zé)任鏈模式。例如,請求的處理需要經(jīng)過驗證、日志記錄、緩存等多個處理器進行處理。
動態(tài)選擇處理器:當(dāng)處理器的選擇和順序需要根據(jù)實際情況進行動態(tài)調(diào)整時,可以使用責(zé)任鏈模式。例如,根據(jù)請求的類型或者優(yōu)先級來動態(tài)選擇處理器。
需要對請求進行過濾或攔截的場景:當(dāng)需要對請求進行過濾、攔截或者根據(jù)條件決定是否進行處理時,可以使用責(zé)任鏈模式。例如,對請求進行權(quán)限驗證、安全檢查、數(shù)據(jù)校驗等操作。
減少耦合,提高系統(tǒng)的靈活性和可維護性:當(dāng)需要降低發(fā)送者和接收者之間的耦合度,以及提高系統(tǒng)的靈活性和可維護性時,可以考慮使用責(zé)任鏈模式。
總之,責(zé)任鏈模式適用于處理請求鏈路較長、處理器之間松耦合、需要動態(tài)組織和處理請求的場景。它可以幫助我們實現(xiàn)更靈活、可擴展和可維護的系統(tǒng)設(shè)計。
實踐案例
下面結(jié)合自定義注解和@Aspect,我們可以實現(xiàn)對組件的增強,使其具備責(zé)任鏈模式的功能。
首先,我們需要定義一個自定義注解,用于標(biāo)識需要應(yīng)用責(zé)任鏈模式的方法或類??梢远x如下注解:
package com.example.demo.design.chain;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyChain {}
接下來,我們使用@Aspect注解創(chuàng)建一個切面類,在切面類中實現(xiàn)責(zé)任鏈模式的邏輯??梢远x如下切面類
package com.example.demo.design.chain;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.List;
@Aspect
@Component
public class ChainHandlerAspect implements InitializingBean {
@Autowired
// 注入所有實現(xiàn)ChainHandler接口的責(zé)任鏈處理器
private List<ChainHandler> chainHandlers;
// 責(zé)任鏈的頭節(jié)點
private ChainHandler chainHandler;
@Around("@annotation(com.example.demo.design.chain.MyChain)")
public Object checkParam(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs(); // 獲取方法的所有參數(shù)
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
Class<?>[] parameterTypes = method.getParameterTypes(); // 獲取方法的參數(shù)類型列表
for (int i = 0; i < parameterTypes.length; i++) {
if (parameterTypes[i].getName().equals("java.lang.String")) {
chainHandler.handle(new Request((String) args[0]));
}
}
return pjp.proceed();
}
/**
* 構(gòu)建處理器鏈
*/
private ChainHandler buildHandlerChain() {
ChainHandler headChainHandler = null;
ChainHandler currentChainHandler = null;
for (ChainHandler chainHandler : chainHandlers) {
if (headChainHandler == null) {
headChainHandler = chainHandler;
currentChainHandler = headChainHandler;
} else {
currentChainHandler.setNextHandler(chainHandler);
currentChainHandler = chainHandler;
}
}
return headChainHandler;
}
@Override
public void afterPropertiesSet() throws Exception {
// 構(gòu)建責(zé)任鏈
chainHandler = this.buildHandlerChain();
}
}
責(zé)任鏈相關(guān)組件
處理器接口
package com.example.demo.design.chain;
public interface ChainHandler {
void handle(Request request);
void setNextHandler(ChainHandler handler);
}
處理器實現(xiàn)類
package com.example.demo.design.chain;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(1)
public class FirstHandler implements ChainHandler {
private ChainHandler nextHandler;
@Override
public void handle(Request request) {
// 處理請求
System.out.println("FirstHandler handling request " + request);
// 將請求傳遞給下一個處理器
if (nextHandler != null) {
nextHandler.handle(request);
}
}
@Override
public void setNextHandler(ChainHandler handler) {
this.nextHandler = handler;
}
}
package com.example.demo.design.chain;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(2)
public class SecondHandler implements ChainHandler {
private ChainHandler nextHandler;
@Override
public void handle(Request request) {
// 處理請求
System.out.println("SecondHandler handling request " + request);
// 將請求傳遞給下一個處理器
if (nextHandler != null) {
nextHandler.handle(request);
}
}
@Override
public void setNextHandler(ChainHandler handler) {
this.nextHandler = handler;
}
}
package com.example.demo.design.chain;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(3)
public class ThirdHandler implements ChainHandler {
private ChainHandler nextHandler;
@Override
public void handle(Request request) {
// 處理請求
System.out.println("ThirdHandler handling request " + request);
}
@Override
public void setNextHandler(ChainHandler handler) {
this.nextHandler = handler;
}
}
以上代碼是類同的,通過@Order注解指定了處理器的執(zhí)行順序,數(shù)字越小,優(yōu)先級越高。
setNextHandler方法用于設(shè)置下一個處理器,接收一個ChainHandler對象作為參數(shù),并將其保存在nextHandler字段中。
Request類
package com.example.demo.design.chain;
public class Request {
private String data;
public Request(String data) {
this.data = data;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
@Override
public String toString() {
return "Request{" +
"data='" + data + ''' +
'}';
}
}
業(yè)務(wù)代碼組件
package com.example.demo.design.chain;
import org.springframework.stereotype.Component;
@Component
public class BizComponent {
@MyChain
public void process(String data) {
System.out.println(data);
}
}
@MyChain注解用于標(biāo)記需要應(yīng)用責(zé)任鏈模式的方法或類。
啟動類
package com.example.demo.design.chain;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@SpringBootApplication
@EnableAspectJAutoProxy
public class Application {
public static void main(String[] args) {
SpringApplication.run(com.example.demo.design.chain.Application.class, args);
}
}
@EnableAspectJAutoProxy注解用于啟用AspectJ自動代理功能,使得Spring能夠識別和應(yīng)用切面。
package com.example.demo.design.chain;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
@Data
public class ComponentRunner implements CommandLineRunner {
@Autowired
private BizComponent bizComponent;
@Override
public void run(String... args) throws Exception {
// 執(zhí)行某個方法(帶Chain注解)
bizComponent.process("Hello world!");
}
}
該組件類的執(zhí)行邏輯是在應(yīng)用程序啟動后自動執(zhí)行的,可以根據(jù)實際需求,在run方法中編寫適當(dāng)?shù)臉I(yè)務(wù)邏輯和處理流程。
主要是為了模擬發(fā)起請求,可以使用Controller訪問的方式。
**執(zhí)行效果 **

我們可以看到,在執(zhí)行bizComponent.process("Hello world!")之前,我們已經(jīng)被注解@MyChain進行增強處理了,所以會經(jīng)過責(zé)任鏈進行前置處理。
總結(jié)
通過這種方式,我們可以靈活地擴展和定制責(zé)任鏈的處理邏輯,通過注解和AOP的方式將責(zé)任鏈與業(yè)務(wù)組件進行解耦,實現(xiàn)組件的增強和復(fù)用。
責(zé)任鏈模式的應(yīng)用場景很廣泛,例如在Web開發(fā)中,可以使用責(zé)任鏈模式來處理請求的攔截、驗證、日志記錄等操作;在工作流引擎中,可以使用責(zé)任鏈模式來實現(xiàn)任務(wù)的處理和流轉(zhuǎn);在事件驅(qū)動系統(tǒng)中,可以使用責(zé)任鏈模式來處理事件的觸發(fā)和傳遞等等。
通過結(jié)合自定義注解和Spring的AOP功能,我們可以更加方便地應(yīng)用責(zé)任鏈模式,并在開發(fā)過程中獲得更高的可擴展性和靈活性。這種組件增強的方式使得責(zé)任鏈模式的實現(xiàn)更加簡潔、可讀性更高,同時也提升了代碼的可維護性和可測試性。
總而言之,使用自定義注解和@Aspect實現(xiàn)責(zé)任鏈模式的組件增強,是一種強大的編程技巧,能夠有效地將責(zé)任鏈的邏輯與業(yè)務(wù)組件解耦,提供了一種靈活且可擴展的方式來處理請求和邏輯鏈的處理。這種結(jié)合注解和AOP的方式,使得責(zé)任鏈模式的應(yīng)用更加簡單、優(yōu)雅,為我們的開發(fā)工作帶來了便利和效益。
以上就是使用自定義注解和@Aspect實現(xiàn)責(zé)任鏈模式的組件增強的詳細代碼的詳細內(nèi)容,更多關(guān)于自定義注解和@Aspect實現(xiàn)組件增強的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
談?wù)凧ava中整數(shù)類型(short int long)的存儲方式
在java中的整數(shù)類型有四種,分別是byte short in long,本文重點給大家介紹java中的整數(shù)類型(short int long),由于byte只是一個字節(jié)0或1,在此就不多說了,對java中的整數(shù)類型感興趣的朋友一起學(xué)習(xí)吧2015-11-11
JAVA不可變類(immutable)機制與String的不可變性(推薦)
這篇文章主要介紹了JAVA不可變類(immutable)機制與String的不可變性(推薦)的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-08-08
詳解RabbitMQ中延遲隊列結(jié)合業(yè)務(wù)場景的使用
這篇文章主要介紹了詳解RabbitMQ中延遲隊列結(jié)合業(yè)務(wù)場景的使用,延遲隊列中的元素都是帶有時間屬性的,延遲隊列就是用來存放需要在指定時間被處理的元素的隊列,需要的朋友可以參考下2023-05-05
java調(diào)用python代碼的兩種實現(xiàn)方式:Runtime.exec()和Jython
在Java中調(diào)用Python代碼有多種方法,包括使用Runtime.exec()和第三方庫如Jython,Runtime.exec()通過系統(tǒng)命令執(zhí)行Python腳本,適用于簡單的調(diào)用場景,Jython則是一個Python的Java實現(xiàn),允許在Java中直接運行Python代碼,適用于更深層次的集成需求2025-01-01
利用Spring?boot+LogBack+MDC實現(xiàn)鏈路追蹤
這篇文章主要介紹了利用Spring?boot+LogBack+MDC實現(xiàn)鏈路追蹤,MDC?可以看成是一個與當(dāng)前線程綁定的哈希表,可以往其中添加鍵值對,下文詳細介紹需要的小伙伴可以參考一下2022-04-04

