JavaRush /Блоги Java /Random-TG /AOP чист? Асосҳои барномасозии ба ҷанба нигаронидашуда

AOP чист? Асосҳои барномасозии ба ҷанба нигаронидашуда

Дар гурӯҳ нашр шудааст
Салом бачаҳо! Бе фаҳмидани мафҳумҳои асосӣ, омӯхтани чаҳорчӯба ва равишҳои сохтани функсияҳо хеле душвор аст. Ҳамин тавр, имрӯз мо дар бораи яке аз ин мафҳумҳо сӯҳбат хоҳем кард - AOP ё барномасозии ба ҷанба нигаронидашуда . AOP чист?  Асосҳои барномасозии ба ҷанба нигаронидашуда - 1Ин мавзӯи осон нест ва аксар вақт мустақиман истифода намешавад, аммо бисёр чаҳорчӯбаҳо ва технологияҳо онро дар зери сарпӯш истифода мебаранд. Ва албатта, баъзан ҳангоми мусоҳиба аз шумо хоҳиш карда мешавад, ки ба таври умумӣ бигӯед, ки ин чӣ гуна ҳайвон аст ва дар куҷо истифода мешавад. Пас, биёед ба мафҳумҳои асосӣ ва баъзе мисолҳои оддии AOP дар Java назар андозем . AOP чист?  Асосҳои барномасозии ба ҷанба нигаронидашуда - 2Ҳамин тавр, AOP - барномасозии ба ҷанба нигаронидашуда - парадигмаест, ки ба баланд бардоштани модулияти қисмҳои гуногуни барнома тавассути ҷудо кардани нигарониҳои байниҳамдигар нигаронида шудааст. Барои ин, рафтори иловагӣ ба рамзи мавҷуда, бе тағир додани рамзи аслӣ илова карда мешавад. Ба ибораи дигар, ба назар чунин мерасад, ки мо дар болои усулҳо ва синфҳо функсияҳои иловагиро овезон кардаем, бидуни ворид кардани тағирот ба codeи тағирёфта. Чаро ин зарур аст? Дер ё зуд мо ба хулосае меоем, ки муносибати мукаррарии ба an object нигаронидашуда на хамеша масъалахои муайянро самаранок хал карда метавонад. Дар чунин лаҳза, AOP ба наҷот меояд ва ба мо барои сохтани барнома асбобҳои иловагӣ медиҳад. Ва абзорҳои иловагӣ маънои афзоиши чандирии рушдро доранд, ки ба шарофати он имконоти бештари ҳалли мушкилоти мушаххас мавҷуданд.

Татбиқи AOP

Барномасозии ба ҷанба нигаронидашуда барои ҳалли масъалаҳои байниҳамдигарӣ тарҳрезӣ шудааст, ки он метавонад ҳама гуна codeе бошад, ки бо тарзҳои гуногун борҳо такрор мешавад, ки онро пурра ба модули алоҳида сохтан мумкин нест. Мутаносибан, бо AOP мо метавонем онро берун аз рамзи асосӣ гузорем ва онро амудӣ муайян кунем. Намунаи татбиқи сиёсати амният дар барнома мебошад. Одатан, амният аз бисёр унсурҳои барнома бурида мешавад. Ғайр аз он, сиёсати амнияти барнома бояд ба ҳама қисмҳои мавҷуда ва нави барнома баробар татбиқ карда шавад. Дар баробари ин, сиёсати амнияти истифодашаванда метавонад худаш инкишоф ёбад. Дар ин ҷо истифодаи AOP метавонад муфид бошад . Инчунин мисоли дигар сабт кардан аст . Истифодаи равиши AOP дар бақайдгирӣ дар муқоиса бо ба таври дастӣ ворид кардани сабт чанд бартариҳо мавҷуданд:
  1. Рамзи сабти номро иҷро кардан ва хориҷ кардан осон аст: ба шумо танҳо лозим аст, ки якчанд конфигуратсияҳои баъзе ҷанбаҳоро илова ё хориҷ кунед.
  2. Ҳама codeи сарчашма барои сабткунӣ дар як ҷо нигоҳ дошта мешавад ва ба таври дастӣ пайдо кардани ҳама ҷойҳои истифода зарурат нест.
  3. Рамзе, ки барои сабти ном пешбинӣ шудааст, метавонад дар ҳама ҷо илова карда шавад, хоҳ усулҳо ва синфҳои аллакай навишташуда ё функсияҳои нав. Ин шумораи хатогиҳои таҳиягарро коҳиш медиҳад.
    Инчунин, вақте ки шумо як ҷанбаро аз конфигуратсияи тарроҳӣ хориҷ мекунед, шумо комилан итминон дошта метавонед, ки ҳама рамзи пайгирӣ хориҷ карда шудааст ва ҳеҷ чиз намерасад.
  4. Ҷанбаҳо рамзи мустақил мебошанд, ки онҳоро такроран истифода ва такмил додан мумкин аст.
AOP чист?  Асосҳои барномасозии ба ҷанба нигаронидашуда - 3AOP инчунин барои коркарди истисноӣ, кэш ва нест кардани баъзе функсияҳо барои дубора истифодашаванда истифода мешавад.

Мафҳумҳои асосии AOP

Барои пешрафти минбаъда дар таҳлor мавзӯъ, биёед аввал бо мафҳумҳои асосии AOP шинос шавем. Маслиҳат мантиқи иловагӣ, codeест, ки аз нуқтаи пайваст даъват карда мешавад. Маслиҳатро метавон пеш, баъд ё ба ҷои нуқтаи пайваст иҷро кард (бештар дар бораи онҳо дар поён). Намудҳои имконпазири маслиҳат :
  1. Пеш аз (Пеш) - маслиҳати ин намуди пеш аз иҷрои усулҳои мақсаднок - нуқтаҳои пайвастшавӣ оғоз карда мешавад. Ҳангоми истифодаи ҷанбаҳо ҳамчун дарсҳо, мо шарҳи @Before -ро мегирем , то навъи маслиҳатро ҳамчун пештара қайд кунем. Ҳангоми истифодаи ҷанбаҳо ҳамчун файлҳои .aj , ин усули пештар() хоҳад буд .
  2. После (After) — советы, которые выполняются после завершения выполнения методов — точек соединения, How в обычных случаях, так и при бросании исключения.
    При использовании аспектов в виде классов мы можем использовать @After аннотацию для указания, что это совет, идущий после.
    При использовании аспектов в виде файлов .aj это будет метод after().
  3. После возврата (After Returning) — данные советы выполняются только в том случае, когда целевой метод отрабатывает нормально, без ошибок.
    Когда аспекты представлены в виде классов, мы можем использовать аннотацию @AfterReturning, чтобы пометить совет How выполняемый после успешного завершения.
    При использовании аспектов в виде файлов .aj это будет метод after() returning (Object obj).
  4. После бросания (After Throwing) — данный вид советов предназначен для тех случаев, когда метод, то есть точка соединения выдает исключение. Мы можем использовать этот совет для некой обработки неудачного выполнения (к примеру, для отката всей транзакции or логирования с необходимым уровнем трассировки).
    Для аспектов-классов annotation @AfterThrowing используется, чтобы указать, что этот совет используется при после броска исключения.
    При использовании аспектов в виде файлов .aj это будет метод — after() throwing (Exception e).
  5. Вокруг (Around) — пожалуй, один из самых важных видов советов, который окружает метод, то есть — точку соединения, с помощью которого мы можем, к примеру, выбрать, выполнять данный метод точки соединения or нет.
    Можно написать code совета, который будет выполняться до и после выполнения метода точки соединения.
    В обязанности around advice входит вызов метода точки соединения и возвращение значений, если метод что-то возвращает. То есть в этом совете можно попросту сымитировать работу целевого метода, не вызывая его, и в качестве результата вернуть что-то свое.
    При аспектах в виде классов используем @Around аннотацию для создания советов, оборачивающих точку соединения. При использовании аспектов в виде файлов .aj это будет метод around().
Нуқтаи пайвастшавӣ - нуқтае дар барномаи иҷрошаванда (даъват ба усул, сохтани an object, дастрасӣ ба тағирёбанда), ки дар он маслиҳат бояд татбиқ карда шавад. Ба ибораи дигар, ин як навъ ифодаи муқаррарист, ки бо ёрии он ҷойҳо барои ҷорӣ кардани code (ҷойҳо барои татбиқи маслиҳатҳо) пайдо мешаванд. Нуқтабурӣ маҷмӯи нуқтаҳои пайвастшавӣ мебошад . Буриш муайян мекунад, ки оё нуқтаи пайвасти додашуда ба нӯги додашуда мувофиқат мекунад. Aspect модул ё синфест, ки функсияҳои охири ба охирро амалӣ мекунад. Ҷанба рафтори қисми боқимондаи codeро тавассути истифодаи маслиҳат дар нуқтаҳои пайвастшавӣ , ки аз ҷониби баъзе бурида муайян шудааст, тағир медиҳад . Ба ибораи дигар, он маҷмӯи маслиҳатҳо ва нуқтаҳои пайвастшавӣ аст. Муқаддима - тағир додани сохтори синф ва/ё тағир додани иерархияи мерос барои илова кардани функсияҳои ҷанба ба рамзи хориҷӣ. Ҳадаф an objectест, ки маслиҳат ба он татбиқ карда мешавад. Бофтан ин раванди пайваст кардани ҷанбаҳо бо дигар an objectҳо барои сохтани an objectҳои прокси тавсияшаванда мебошад. Ин метавонад дар вақти компиляция, вақти боркунӣ ё вақти иҷро анҷом дода шавад. Се намуди бофандагӣ вуҷуд дорад:
  • Бофтан дар вақти ҷамъоварӣ - Агар шумо рамзи сарчашмаи ҷанба ва codeеро, ки дар он ҷанбаҳоро истифода мекунед, дошта бошед, шумо метавонед codeи манбаъ ва ҷанбаро мустақиман бо истифода аз компилятори AspectJ тартиб диҳед;
  • бофандагии пас аз ҷамъоварӣ (бофтани дуӣ) - агар шумо натавонед ё нахоҳед, ки тағиротҳои codeи ибтидоиро барои бофтани ҷанбаҳои codeи худ истифода баред, шумо метавонед дарсҳо ё зарфҳои аллакай тартибдодашударо бигиред ва ҷанбаҳоро ворид кунед;
  • бофандагӣ бофандагии дуӣ аст, то он даме ки боркунаки синф файли синфро бор кунад ва синфро барои JVM муайян кунад, ба таъхир гузошта мешавад.
    Барои дастгирии ин, як ё якчанд "боркунакҳои синфи бофандагӣ" лозиманд. Онҳо ё ба таври возеҳ аз ҷониби вақти корӣ таъмин карда мешаванд ё аз ҷониби "агенти бофандагӣ" фаъол карда мешаванд.
AspectJ як амали мушаххаси парадигмаҳои AOP мебошад , ки қобorяти ҳалли мушкилоти байниҳамдигарро амалӣ мекунад. Ҳуҷҷатҳоро дар ин ҷо пайдо кардан мумкин аст .

Намунаҳо дар Java

Минбаъд, барои беҳтар фаҳмидани AOP, мо ба мисолҳои хурди сатҳи Hello World назар хоҳем кард. AOP чист?  Асосҳои барномасозии ба ҷанба нигаронидашуда - 4Иҷозат диҳед фавран қайд кунам, ки дар мисолҳои худ мо бофандагии компилятиро истифода хоҳем кард . Аввалан мо бояд вобастагии зеринро ба pom.xml- и худ илова кунем :
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjrt</artifactId>
  <version>1.9.5</version>
</dependency>
Чун қоида, барои истифодаи ҷанбаҳо компилятори махсуси Ajs истифода мешавад . IntelliJ IDEA онро ба таври нобаёнӣ надорад, бинобар ин ҳангоми интихоби он ҳамчун компилятори барнома шумо бояд роҳро ба тақсимоти AspectJ муайян кунед . Шумо метавонед бештар дар бораи усули интихоби Ajs ҳамчун компилятор дар ин саҳифа хонед. Ин усули аввал буд ва дуюмаш (ки ман истифода кардам) илова кардани плагини зерин ба pom.xml буд :
<build>
  <plugins>
     <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <version>1.7</version>
        <configuration>
           <complianceLevel>1.8</complianceLevel>
           <source>1.8</source>
           <target>1.8</target>
           <showWeaveInfo>true</showWeaveInfo>
           <verbose>true</verbose>
           <Xlint>ignore</Xlint>
           <encoding>UTF-8</encoding>
        </configuration>
        <executions>
           <execution>
              <goals>
                 <goal>compile</goal>
                 <goal>test-compile</goal>
              </goals>
           </execution>
        </executions>
     </plugin>
  </plugins>
</build>
Пас аз ин, тавсия дода мешавад, ки аз Maven дубора ворид кунед ва mvn clean compile -ро иҷро кунед . Акнун биёед ба мисолҳо мегузарем.

Мисоли № 1

Биёед синфи асосӣ эҷод кунем . Дар он мо нуқтаи оғозёбӣ ва усуле хоҳем дошт, ки номҳои ба он дар консол интиқолшударо чоп мекунад:
public class Main {

  public static void main(String[] args) {
  printName("Толя");
  printName("Вова");
  printName("Sasha");
  }

  public static void printName(String name) {
     System.out.println(name);
  }
}
Ҳеҷ чиз мураккаб нест: онҳо номро гузаштанд ва онро дар консол нишон доданд. Агар мо онро ҳозир иҷро кунем, консол нишон медиҳад:
Толя Вова Саша
Хуб, вақти он расидааст, ки аз қудрати AOP истифода барем. Ҳоло мо бояд як ҷанбаи файл эҷод кунем . Онҳо дар ду намуд меоянд: якум файл бо тамдиди .aj , дуюм синфи муқаррарӣ мебошад, ки қобorятҳои AOP-ро бо истифода аз эзоҳҳо амалӣ мекунад. Биёед аввал файлеро бо тамдиди .aj бубинем :
public aspect GreetingAspect {

  pointcut greeting() : execution(* Main.printName(..));

  before() : greeting() {
     System.out.print("Привет ");
  }
}
Ин файл то андозае ба синф монанд аст. Биёед бифаҳмем, ки дар ин ҷо чӣ рӯй медиҳад: pointcut - буриш ё маҷмӯи нуқтаҳои пайвастшавӣ; салом() — номи ин порча; : иҷро - ҳангоми иҷрои * - ҳама, занг занед - Main.printName(..) - ин усул. Баъдан маслиҳати мушаххас меояд - before() - ки пеш аз даъват кардани усули ҳадаф иҷро мешавад, : salom() - порчае, ки ин маслиҳат ба он вокуниш нишон медиҳад ва дар зер мо ҷузъи худи усулро мебинем, ки дар Java навишта шудааст. забоне, ки мо мефаҳмем. Вақте ки мо бо ин ҷанбаи мавҷуда main -ро иҷро мекунем , мо ба консол натиҷаи зеринро мегирем:
Салом Толя Салом Вова Салом Саша
Мо мебинем, ки ҳар як занг ба усули printName бо як ҷанба тағир дода шудааст. Акнун биёед бубинем, ки ҷанба чӣ гуна хоҳад буд, аммо ҳамчун синфи Java бо эзоҳҳо:
@Aspect
public class GreetingAspect{

  @Pointcut("execution(* Main.printName(String))")
  public void greeting() {
  }

  @Before("greeting()")
  public void beforeAdvice() {
     System.out.print("Привет ");
  }
}
Пас аз файли .aj aspect ҳама чиз равшантар аст:
  • @Aspect маънои онро дорад, ки синфи додашуда ҷанба аст;
  • @Pointcut("execution(* Main.printName(String))") нуқтаи буришест, ки дар ҳама зангҳо ба Main.printName бо аргументи воридотии навъи String оташ мезанад ;
  • @Before("салом()") - маслиҳате, ки пеш аз занг задани рамзи дар нуқтаи буриши салом() тавсифшуда истифода мешавад .
Иҷроиши main бо ин ҷиҳат натиҷаи консолро тағир намедиҳад:
Салом Толя Салом Вова Салом Саша

Мисоли № 2

Фарз мекунем, ки мо як усул дорем, ки барои муштариён баъзе амалиётҳоро иҷро мекунад ва ин усулро аз main даъват мекунад :
public class Main {

  public static void main(String[] args) {
  makeSomeOperation("Толя");
  }

  public static void makeSomeOperation(String clientName) {
     System.out.println("Выполнение некоторых операций для клиента - " + clientName);
  }
}
Бо истифода аз шарҳи @Around , биёед кореро ба мисли "псевдомараксия" иҷро кунем:
@Aspect
public class TransactionAspect{

  @Pointcut("execution(* Main.makeSomeOperation(String))")
  public void executeOperation() {
  }

  @Around(value = "executeOperation()")
  public void beforeAdvice(ProceedingJoinPoint joinPoint) {
     System.out.println("Открытие транзакции...");
     try {
        joinPoint.proceed();
        System.out.println("Закрытие транзакции....");
     }
     catch (Throwable throwable) {
        System.out.println("Операция не удалась, откат транзакции...");
     }
  }
  }
Бо истифода аз усули идомаи an objectи ProceedingJoinPoint , мо усули печандаро барои муайян кардани ҷойгоҳи он дар тахта даъват мекунем ва мувофиқан codeро дар усули дар боло будаи joinPoint.proceed(); - ин Пеш аст , ки дар зер аст - Баъд . Агар мо main -ро иҷро кунем , мо дар консол мегирем:
Кушодани муомилот... Иҷрои баъзе амалиётҳо барои муштарӣ - Толя Бастани муомилот....
Агар мо ба усули худ як истисноро илова кунем (ногаҳон амалиёт ноком мешавад):
public static void makeSomeOperation(String clientName)throws Exception {
  System.out.println("Выполнение некоторых операций для клиента - " + clientName);
  throw new Exception();
}
Пас мо натиҷаро дар консол мегирем:
Кушодани муомилот... Иҷрои баъзе амалиётҳо барои муштарӣ - Толя Амалиёт ноком шуд, транзаксия баргардонида шуд...
Ин як коркарди псевдо-коркарди нокомӣ шуд.

Мисоли № 3

Ҳамчун мисоли навбатӣ, биёед коре кунем, ба монанди воридшавӣ дар консол. Аввалан, биёед Main -ро бубинем , ки дар он мантиқи псевдобизнес мо рух медиҳад:
public class Main {
  private String value;

  public static void main(String[] args) throws Exception {
     Main main = new Main();
     main.setValue("<некоторое meaning>");
     String valueForCheck = main.getValue();
     main.checkValue(valueForCheck);
  }

  public void setValue(String value) {
     this.value = value;
  }

  public String getValue() {
     return this.value;
  }

  public void checkValue(String value) throws Exception {
     if (value.length() > 10) {
        throw new Exception();
     }
  }
}
Дар main , бо истифода аз setValue, мо арзиши тағирёбандаи дохorро муқаррар мекунем - value , пас бо истифода аз getValue, мо ин арзишро мегирем ва дар checkValue месанҷем, ки оё ин арзиш аз 10 аломат дарозтар аст. Агар ҳа, истисно партофта мешавад. Акнун биёед ба ҷанбаи он назар андозем, ки мо амалиёти усулҳоро қайд мекунем:
@Aspect
public class LogAspect {

  @Pointcut("execution(* *(..))")
  public void methodExecuting() {
  }

  @AfterReturning(value = "methodExecuting()", returning = "returningValue")
  public void recordSuccessfulExecution(JoinPoint joinPoint, Object returningValue) {
     if (returningValue != null) {
        System.out.printf("Успешно выполнен метод - %s, класса- %s, с результатом выполнения - %s\n",
              joinPoint.getSignature().getName(),
              joinPoint.getSourceLocation().getWithinType().getName(),
              returningValue);
     }
     else {
        System.out.printf("Успешно выполнен метод - %s, класса- %s\n",
              joinPoint.getSignature().getName(),
              joinPoint.getSourceLocation().getWithinType().getName());
     }
  }

  @AfterThrowing(value = "methodExecuting()", throwing = "exception")
  public void recordFailedExecution(JoinPoint joinPoint, Exception exception) {
     System.out.printf("Метод - %s, класса- %s, был аварийно завершен с исключением - %s\n",
           joinPoint.getSignature().getName(),
           joinPoint.getSourceLocation().getWithinType().getName(),
           exception);
  }
}
Дар ин ҷо чӣ гап? @Pointcut("execution(* *(..))") - ба ҳама зангҳо ба ҳама усулҳо пайваст мешавад; @AfterReturning(value = "methodExecuting()", returning = "returningValue") - маслиҳате, ки пас аз бомуваффақият анҷом ёфтани усули мақсаднок иҷро карда мешавад. Мо дар ин ҷо ду ҳолат дорем:
  1. Вақте ки усул арзиши баргардонидан дорад, агар (returningValue != null) {
  2. Вақте ки арзиши баргардонидани дигар вуҷуд надорад {
@AfterThrowing(value = "methodExecuting()", throwing = "истисно") - маслиҳате, ки дар сурати хатогӣ, яъне вақте ки истисно аз метод хориҷ карда мешавад, дода мешавад. Ва мутаносибан, бо иҷро кардани main , мо дар консол як навъ сабти номро мегирем:
Усули - setValue, аз синф - Main бомуваффақият иҷро шуд. Усули - getValue, аз синф - Main, бомуваффақият иҷро шуд, бо натиҷаи иҷро - <баъзе арзиш> Усули - checkValue, аз синф - Main, ба таври ғайримуқаррарӣ қатъ карда шуд, ба истиснои - java.lang.Exception Усули - асосӣ, синф-Main, ба истиснои ҳолати садама дучор шуд - java.lang.Exception
Хуб, азбаски мо истисноро ҳал накардем, мо инчунин сттектри онро мегирем: AOP чист?  Асосҳои барномасозии ба ҷанба нигаронидашуда - 5Шумо метавонед дар бораи истисноҳо ва коркарди онҳо дар ин мақолаҳо хонед: Истисноҳо дар Java ва Истисноҳо ва коркарди онҳо . Ин ҳама барои ман имрӯз аст. Имрӯз мо бо AOP шинос шудем ва шумо мебинед, ки ин ҳайвони ваҳшӣ он қадар даҳшатнок нест, ки ранг карда шудааст. Салом ба ҳама!AOP чист?  Асосҳои барномасозии ба ҷанба нигаронидашуда - 6
Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION