日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

面向切面编程应用_应用面向方面的编程

發(fā)布時(shí)間:2023/12/3 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面向切面编程应用_应用面向方面的编程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

面向切面編程應(yīng)用

1.引言

面向方面編程的主要目標(biāo)是將跨領(lǐng)域關(guān)注點(diǎn)分離。 當(dāng)我們談?wù)摽珙I(lǐng)域的關(guān)注時(shí),我們指的是在我們的系統(tǒng)或應(yīng)用程序中的多個(gè)地方使用的通用功能。 這些概念包括:

  • 記錄中
  • 交易管理
  • 錯(cuò)誤處理
  • 監(jiān)控方式
  • 安全

實(shí)現(xiàn)這種分離的方法是將這些概念模塊化。 這將使我們保持業(yè)務(wù)邏輯類整潔,僅包含設(shè)計(jì)該類的代碼。 如果我們不對(duì)這些問題進(jìn)行模塊化,則會(huì)導(dǎo)致代碼糾結(jié)(該類包含不同的問題)和代碼分散(相同的問題將散布在整個(gè)系統(tǒng)中)。

在此示例中,我們有一個(gè)Spring MVC應(yīng)用程序,該應(yīng)用程序訪問所請(qǐng)求的數(shù)據(jù)(客戶和訂單)并顯示一個(gè)包含其信息的頁(yè)面。 我們可以看一下不同的層:

在上圖中,我們可以理解,功能分散在不同的類中(在每個(gè)服務(wù)中實(shí)現(xiàn)監(jiān)視),并且某些類包含不同的關(guān)注點(diǎn)(例如,ClientController類包含日志記錄和異常處理)。 為了解決這個(gè)問題,我們將編寫一些方面來實(shí)現(xiàn)我們的跨領(lǐng)域關(guān)注點(diǎn)。 目標(biāo)是實(shí)現(xiàn)以下模型:

每個(gè)類僅包含與業(yè)務(wù)邏輯相關(guān)的代碼,而各方面將負(fù)責(zé)攔截代碼以注入跨領(lǐng)域的關(guān)注點(diǎn)。

讓我們看一個(gè)例子。

  • 源代碼可以在github上找到。

2.檢查控制器代碼

ClientController:

@Controller public class ClientController {@Autowiredprivate ClientService clientService;private static Logger mainLogger = LoggerFactory.getLogger("generic");private static Logger errorLogger = LoggerFactory.getLogger("errors");@RequestMapping("/getClients")public String getClients(Model model, @RequestParam("id") int id) {mainLogger.debug("Executing getClients request");try {Client client = clientService.getClient(id);model.addAttribute("client", client);} catch (DataAccessException e) {errorLogger.error("error in ClientController", e);NotificationUtils.sendNotification(e);return "errorPage";}return "showClient";} }

該控制器的目的在于檢索一個(gè)客戶端并返回一個(gè)顯示其信息的視圖,但是,如您所見,該代碼包含其他邏輯。 一方面,它處理服務(wù)可能引發(fā)的異常,并將其重定向到錯(cuò)誤頁(yè)面。 另一方面,如果發(fā)生錯(cuò)誤,它會(huì)生成日志記錄信息和通知發(fā)送。 所有這些代碼對(duì)于該應(yīng)用程序中的所有控制器(可能還有其他類)都是通用的。

的確,我們本可以使用@ControllerAdvice批注來集中處理異常,但是本文的目標(biāo)是了解如何使用Spring AOP完成它。

訂單控制器也會(huì)發(fā)生同樣的情況。 我不會(huì)在這里包括它,因?yàn)槲也幌胱屘幼兊枚嘤唷?如果您想檢查一下,可以獲取上一個(gè)鏈接中包含的源代碼。

3.檢查服務(wù)代碼

客戶服務(wù):

@Service("clientService") public class ClientServiceImpl implements ClientService {@Autowiredprivate ClientRepository clientRepository;private static Logger mainLogger = LoggerFactory.getLogger("generic");private static Logger monitorLogger = LoggerFactory.getLogger("monitoring");@Override@Transactional(readOnly = true)public Client getClient(int id) {mainLogger.debug("Accessing client service");long startTime = System.currentTimeMillis();Client client = clientRepository.getClient(id);long totalTime = System.currentTimeMillis() - startTime;monitorLogger.info("Invocation time {}ms ", totalTime);return client;} }

除了服務(wù)調(diào)用外,它還包含日志記錄的生成和每個(gè)調(diào)用中執(zhí)行時(shí)間的監(jiān)視。

如果需要使用程序化事務(wù)管理,我們還可以使用方面來模塊化事務(wù)管理,但是在本示例中并非如此。

4.數(shù)據(jù)訪問層

ClientRepositoryImpl:

@Repository public class ClientRepositoryImpl implements ClientRepository {private JdbcTemplate template;private RowMapper<Client> rowMapper = new ClientRowMapper();private static final String SEARCH = "select * from clients where clientId = ?";private static final String COLUMN_ID = "clientId";private static final String COLUMN_NAME = "name";public ClientRepositoryImpl() {}public ClientRepositoryImpl(DataSource dataSource) {this.template = new JdbcTemplate(dataSource);}public Client getClient(int id) {return template.queryForObject(SEARCH, rowMapper, id);}private class ClientRowMapper implements RowMapper<Client> {public Client mapRow(ResultSet rs, int i) throws SQLException {Client client = new Client();client.setClientId(rs.getInt(COLUMN_ID));client.setName(rs.getString(COLUMN_NAME));return client;}} }

該代碼不包含任何橫切關(guān)注點(diǎn),但我將其包括在內(nèi)以顯示所有示例應(yīng)用程序?qū)印?

5,激活A(yù)OP

要配置AOP,必須導(dǎo)入以下依賴項(xiàng):

<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>3.2.1.RELEASE</version> </dependency> <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.6.8</version> </dependency>

在Spring配置文件中,我們需要添加以下標(biāo)簽:

<context:component-scan base-package="xpadro.spring.mvc.aop"/> <aop:aspectj-autoproxy/>

component-scan標(biāo)簽將在基本包中搜索,以查找我們的方面。 要使用自動(dòng)掃描,您不僅需要使用@Aspect注釋定義方面類,而且還需要包含@Component注釋。 如果不包括@Component,則需要在xml配置文件中定義方面。

6,集中錯(cuò)誤處理

我們將使用@Around建議來編寫方面。 該建議將截獲所有使用@RequestMapping注釋進(jìn)行注釋的方法,并將負(fù)責(zé)調(diào)用該方法,并捕獲服務(wù)引發(fā)的異常。

@Component @Aspect public class CentralExceptionHandler {private static Logger errorLogger = LoggerFactory.getLogger("errors");@Around("@annotation(org.springframework.web.bind.annotation.RequestMapping) && target(controller)")public String handleException(ProceedingJoinPoint jp, Object controller) throws Throwable {String view = null;try {view = (String) jp.proceed();} catch (DataAccessException e) {errorLogger.error("error in {}", controller.getClass().getSimpleName(), e);NotificationUtils.sendNotification(e);return "errorPage";}return view;} }

@Target批注允許我們引用被攔截的類。 現(xiàn)在我們有了方面處理的異常處理,因此我們可以在控制器中擺脫這種邏輯。

@Controller public class ClientController {@Autowiredprivate ClientService clientService;private static Logger mainLogger = LoggerFactory.getLogger("generic");//private static Logger errorLogger = LoggerFactory.getLogger("errors");@RequestMapping("/getClients")public String getClients(Model model, @RequestParam("id") int id) {mainLogger.debug("Executing getClients request");//try {Client client = clientService.getClient(id);model.addAttribute("client", client);//} catch (DataAccessException e) {//errorLogger.error("error in ClientController", e);//NotificationUtils.sendNotification(e);//return "errorPage";//}return "showClient";} }

僅需注意,您可能會(huì)通過以下建議截獲控制器拋出的異常:

@AfterThrowing(pointcut="@annotation(org.springframework.web.bind.annotation.RequestMapping)", throwing="e")

但是請(qǐng)注意,此建議不會(huì)阻止異常的傳播。

7,集中日志

日志記錄方面有兩個(gè)建議,一個(gè)關(guān)于控制器日志,另一個(gè)關(guān)于服務(wù)日志:

@Aspect @Component public class CentralLoggingHandler {private static Logger mainLogger = LoggerFactory.getLogger("generic");@Before("@annotation(org.springframework.web.bind.annotation.RequestMapping) && @annotation(mapping)")public void logControllerAccess(RequestMapping mapping) {mainLogger.debug("Executing {} request", mapping.value()[0]);}@Before("execution(* xpadro.spring.mvc.*..*Service+.*(..)) && target(service)")public void logServiceAccess(Object service) {mainLogger.debug("Accessing {}", service.getClass().getSimpleName());} }

8.最后,監(jiān)控問題

我們將寫另一個(gè)方面來監(jiān)視關(guān)注。 建議如下:

@Aspect @Component public class CentralMonitoringHandler {private static Logger monitorLogger = LoggerFactory.getLogger("monitoring");@Around("execution(* xpadro.spring.mvc.*..*Service+.*(..)) && target(service)")public Object logServiceAccess(ProceedingJoinPoint jp, Object service) throws Throwable {long startTime = System.currentTimeMillis();Object result = jp.proceed();long totalTime = System.currentTimeMillis() - startTime;monitorLogger.info("{}|Invocation time {}ms ", service.getClass().getSimpleName(), totalTime);return result;} }

9.檢查最終代碼

在將所有交叉問題模塊化后,我們的控制器和服務(wù)僅包含業(yè)務(wù)邏輯:

@Controller public class ClientController {@Autowiredprivate ClientService clientService;@RequestMapping("/getClients")public String getClients(Model model, @RequestParam("id") int id) {Client client = clientService.getClient(id);model.addAttribute("client", client);return "showClient";} }@Service("clientService") public class ClientServiceImpl implements ClientService {@Autowiredprivate ClientRepository clientRepository;@Override@Transactional(readOnly = true)public Client getClient(int id) {return clientRepository.getClient(id);} }

10,結(jié)論

我們已經(jīng)看到了如何應(yīng)用面向方面的編程來保持我們的代碼整潔,并專注于針對(duì)其設(shè)計(jì)的邏輯。 在使用AOP之前,只需考慮其已知的限制。

參考:在XavierPadró的Blog博客上,從我們的JCG合作伙伴 Xavier Padro 應(yīng)用面向方面的編程 。

翻譯自: https://www.javacodegeeks.com/2014/02/applying-aspect-oriented-programming.html

面向切面編程應(yīng)用

總結(jié)

以上是生活随笔為你收集整理的面向切面编程应用_应用面向方面的编程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。