JavaRush /Java блогы /Random-KK /AOP дегеніміз не? Аспектілі бағдарланған бағдарламалау не...
Константин
Деңгей

AOP дегеніміз не? Аспектілі бағдарланған бағдарламалау негіздері

Топта жарияланған
Сәлем балалар! Негізгі ұғымдарды түсінбестен, функционалдылықты құрудың шеңберлері мен тәсілдерін зерттеу өте қиын. Сонымен, бүгін біз осы тұжырымдамалардың бірі - AOP немесе аспектіге бағытталған бағдарламалау туралы сөйлесетін боламыз . AOP дегеніміз не?  Аспектілі бағдарланған бағдарламалау негіздері – 1Бұл оңай тақырып емес және жиі тікелей пайдаланылмайды, бірақ көптеген фреймворктар мен технологиялар оны қақпақтың астында пайдаланады. Әрине, кейде сұхбат кезінде сізден бұл қандай жануар екенін және оны қайда қолдануға болатынын жалпылама түрде айтуды сұрайды. Сонымен, Java тіліндегі AOP-тің негізгі ұғымдары мен кейбір қарапайым мысалдарын қарастырайық . AOP дегеніміз не?  Аспектілі бағдарланған бағдарламалау негіздері – 2Сонымен, AOP - аспектіге бағытталған бағдарламалау - бұл қиылысатын мәселелерді бөлу арқылы қолданбаның әртүрлі бөліктерінің модульділігін арттыруға бағытталған парадигма. Бұл әрекетті орындау үшін, бастапқы codeты өзгертпей, бар codeқа қосымша әрекет қосылады. Басқаша айтқанда, біз өзгертілген codeқа түзетулер енгізбестен әдістер мен сыныптардың үстіне қосымша функционалдылықты іліп қоятын сияқтымыз. Бұл не үшін қажет? Ерте ме, кеш пе, біз әдеттегі an objectіге бағытталған тәсіл әрқашан белгілі бір мәселелерді тиімді шеше алмайды деген қорытындыға келеміз. Осындай сәтте AOP көмекке келеді және бізге қосымшаны құру үшін қосымша құралдар береді. Ал қосымша құралдар дамудағы икемділікті арттыруды білдіреді, соның арқасында белгілі бір мәселені шешудің көптеген нұсқалары бар.

AOP қолдану

Аспект-бағдарланған бағдарламалау әртүрлі тәсілдермен бірнеше рет қайталанатын, жеке модульге толығымен құрылымдауға болмайтын кез келген code болуы мүмкін қиылысатын есептерді шешуге арналған. Тиісінше, AOP көмегімен біз оны негізгі codeтан тыс қалдыра аламыз және оны тігінен анықтай аламыз. Мысал ретінде қолданбадағы қауіпсіздік саясатын қолдану болып табылады. Әдетте, қауіпсіздік қолданбаның көптеген элементтерін кесіп өтеді. Сонымен қатар, қолданбаның қауіпсіздік саясаты қолданбаның барлық бар және жаңа бөліктеріне бірдей қолданылуы керек. Сонымен қатар, қолданылатын қауіпсіздік саясаты өздігінен дами алады. Бұл жерде AOP пайдалану пайдалы болуы мүмкін . Сондай-ақ тағы бір мысал журнал жүргізу . Журналға тіркеуді қолмен енгізумен салыстырғанда, AOP әдісін қолданудың бірнеше артықшылығы бар:
  1. Тіркеу codeын енгізу және жою оңай: сізге тек кейбір аспектілердің бірнеше конфигурациясын қосу немесе жою қажет.
  2. Журналға арналған барлық бастапқы code бір жерде сақталады және барлық пайдалану орындарын қолмен табудың қажеті жоқ.
  3. Тіркеуге арналған codeты кез келген жерде қосуға болады, ол әлдеқашан жазылған әдістер мен сыныптар немесе жаңа функция болсын. Бұл әзірлеуші ​​қателерінің санын азайтады.
    Сондай-ақ, дизайн конфигурациясынан аспектіні жойған кезде, барлық бақылау codeы жойылғанына және ештеңе жоқ екеніне толық сенімді бола аласыз.
  4. Аспекттер қайта пайдалануға және қайта-қайта жақсартуға болатын оқшауланған code болып табылады.
AOP дегеніміз не?  Аспектілі бағдарланған бағдарламалау негіздері – 3Сондай-ақ, AOP қайта пайдалануға болатындай ету үшін ерекше жағдайларды өңдеу, кэштеу және кейбір функцияларды жою үшін қолданылады.

AOP туралы негізгі түсініктер

Тақырыпты талдауда әрі қарай жылжу үшін алдымен AOP негізгі ұғымдарымен танысайық. Кеңес - бұл қосылу нүктесінен шақырылатын қосымша логика, code. Кеңес қосу нүктесінің алдында, кейін немесе оның орнына орындалуы мүмкін (олар туралы толығырақ төменде). Кеңестің мүмкін түрлері :
  1. Бұрын (Бұрын) - осы түрдегі кеңес мақсатты әдістерді - қосылу нүктелерін орындау алдында іске қосылады. Аспекттерді сыныптар ретінде пайдаланған кезде кеңес түрін бұрынғы деп белгілеу үшін @Before annotationсын аламыз . Аспекттерді .aj файлдары ретінде пайдаланған кезде, бұл before() әдісі болады .
  2. Кейін (Кейін) - әдістерді орындау аяқталғаннан кейін орындалатын кеңес - қалыпты жағдайларда да, ерекшелік жойылған кезде де қосылу нүктелері. Аспекттерді сыныптар ретінде пайдаланған кезде, бұл кейін келетін кеңес екенін көрсету үшін @After
    annotationсын пайдалана аламыз . Аспекттерді .aj файлдары ретінде пайдаланған кезде, бұл after() әдісі болады .
  3. Қайтарылғаннан кейін - бұл кеңестер мақсатты әдіс қатесіз қалыпты жұмыс істеген жағдайда ғана орындалады.
    Аспекттер сыныптар ретінде ұсынылған кезде, біз кеңесті сәтті аяқталғаннан кейін орындалды деп белгілеу үшін @AfterReturning annotationсын пайдалана аламыз.
    Аспекттерді .aj файлдары ретінде пайдаланған кезде, бұл (Object obj) қайтаратын after() әдісі болады .
  4. Лақтырудан кейін - бұл кеңес түрі әдіс, яғни қосылым нүктесі ерекше жағдайды шығаратын жағдайларға арналған. Біз бұл кеңесті сәтсіз орындалудың кейбір өңдеуі үшін пайдалана аламыз (мысалы, бүкіл транзакцияны кері қайтару немесе қажетті бақылау деңгейімен тіркеу).
    Аспект сыныптары үшін @AfterThrowing annotationсы бұл кеңес ерекшелік тасталғаннан кейін пайдаланылатынын көрсету үшін пайдаланылады. .aj
    файлдары түріндегі аспектілерді пайдаланған кезде , бұл әдіс - after() тастау (Е ерекшелік) болады .
  5. Around - бұл әдісті қоршайтын кеңестердің ең маңызды түрлерінің бірі, яғни қосылу нүктесі, оның көмегімен біз, мысалы, берілген қосылу нүктесі әдісін орындау немесе орындамауды таңдауға болады.
    Біріктіру нүктесі әдісі орындалғанға дейін және кейін орындалатын кеңес codeын жаза аласыз. Кеңестің
    міндеттеріне біріктіру нүктесі әдісін шақыру және әдіс бір нәрсені қайтарса, мәндерді қайтару кіреді. Яғни, бұл кеңесте сіз мақсатты әдісті шақырмай-ақ оның жұмысын имитациялай аласыз және нәтижесінде өзіңізге ұнайтын нәрсені қайтара аласыз. Сыныптар түріндегі аспектілер үшін біз @Around annotationсын қосылым нүктесін орайтын кеңестер жасау үшін қолданамыз. Аспекттерді .aj файлдары ретінде пайдаланған кезде, бұл around() әдісі болады .
Біріктіру нүктесі – орындаушы бағдарламадағы (әдісті шақыру, an object құру, айнымалыға қол жеткізу) кеңесті қолдану керек нүкте. Басқаша айтқанда, бұл қалыпты өрнектің қандай да бір түрі, оның көмегімен codeты енгізуге арналған орындар (кеңестерді қолдануға арналған орындар) табылады. Нүктелік сызба - қосылу нүктелерінің жиынтығы . Кесу берілген қосылым нүктесінің берілген ұшына сәйкес келетінін анықтайды. Аспект - бұл түпкілікті функционалдылықты жүзеге асыратын модуль немесе класс. Аспект кейбір бөліктермен анықталған біріктіру нүктелерінде кеңестерді қолдану арқылы codeтың қалған бөлігінің әрекетін өзгертеді . Басқаша айтқанда, бұл кеңестер мен байланыс нүктелерінің тіркесімі. Кіріспе – класс құрылымын өзгерту және/немесе мұра иерархиясын шетелдік codeқа аспект функционалдығын қосу үшін өзгерту. Мақсат - кеңес қолданылатын нысан. Тоқу – ұсынылған прокси нысандарын жасау үшін аспектілерді басқа нысандармен байланыстыру процесі. Мұны компиляция уақытында, жүктеу уақытында немесе орындау уақытында жасауға болады. Тоқудың үш түрі бар:
  • Compile-time weaving - Егер сізде аспекттің бастапқы codeы және аспектілерді пайдаланатын code болса, AspectJ компиляторын пайдаланып бастапқы code пен аспектіні тікелей құрастыра аласыз;
  • компиляциядан кейінгі өру (екілік тоқу) - егер сіз codeқа аспектілерді тоқу үшін бастапқы code түрлендірулерін пайдалана алмасаңыз немесе пайдаланғыңыз келмесе, сіз әлдеқашан құрастырылған сыныптарды немесе банкаларды алып, аспектілерді енгізуге болады;
  • жүктеу уақытында тоқу класс жүктеушісі класс файлын жүктеп, JVM үшін классты анықтағанша кейінге қалдырылған жай екілік тоқу.
    Мұны қолдау үшін бір немесе бірнеше «тоқыма класы тиегіштері» қажет. Олар нақты орындалу уақыты арқылы беріледі немесе "тоқыма агенті" арқылы белсендіріледі.
AspectJ - қиылысатын мәселелерді шешу мүмкіндігін жүзеге асыратын AOP парадигмаларының нақты жүзеге асырылуы . Құжаттарды мына жерден табуға болады .

Java тіліндегі мысалдар

Әрі қарай, AOP-ті жақсы түсіну үшін біз Hello World деңгейінің шағын мысалдарын қарастырамыз. Бірден айта кетейін, біздің мысалдарымызда біз компиляция уақытында weavingAOP дегеніміз не?  Аспектілі бағдарланған бағдарламалау негіздері – 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 кеңейтімі бар файл , екіншісі - annotationларды пайдаланып AOP мүмкіндіктерін жүзеге асыратын кәдімгі сынып. Алдымен .aj кеңейтімі бар файлды қарастырайық :
public aspect GreetingAspect {

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

  before() : greeting() {
     System.out.print("Привет ");
  }
}
Бұл файл сыныпқа ұқсас. Мұнда не болып жатқанын анықтайық: нүктелік кесу – кесу немесе қосылу нүктелерінің жиынтығы; greeting() — осы кесіндінің атауы; : орындау - орындау кезінде * - барлығы, шақыру - Main.printName(..) - бұл әдіс. Одан кейін мақсатты әдіс шақырылғанға дейін орындалатын – before() – арнайы кеңес келеді , : greeting() – бұл кеңес жауап беретін бөлік, ал төменде біз Java тілінде жазылған әдістің өзін көреміз. біз түсінетін тіл. Осы аспектпен негізгі іске қосқан кезде консольге келесі нәтижені аламыз:
Сәлем Толя Сәлем Вова Сәлем Саша
PrintName әдісіне әрбір шақыру аспект бойынша өзгертілгенін көреміз . Енді аспект қандай болатынын қарастырайық, бірақ annotationлары бар 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))") String түріндегі кіріс аргументі бар Main.printName қызметіне барлық шақыруларда іске қосылатын кесу нүктесі ;
  • @Before("greeting()") - сәлемдесу() кесу нүктесінде сипатталған codeты шақыру алдында қолданылатын кеңес .
Осы аспектпен main іске қосу консоль шығысын өзгертпейді:
Сәлем Толя Сәлем Вова Сәлем Саша

№2 мысал

Клиенттер үшін кейбір операцияларды орындайтын және бұл әдісті main арқылы шақыратын әдіс бар делік :
public class Main {

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

  public static void makeSomeOperation(String clientName) {
     System.out.println("Выполнение некоторых операций для клиента - " + clientName);
  }
}
@Around annotationсын пайдаланып , «жалған транзакция» сияқты бірдеңені жасайық:
@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("Операция не удалась, откат транзакции...");
     }
  }
  }
ProceedingJoinPoint нысанының жалғастыру әдісін пайдалана отырып , оның тақтадағы орнын және сәйкесінше, жоғарыдағы joinPoint.proceed (); - бұл алдында , төменде - Кейін . Егер біз негізгі іске қоссақ , консольге кіреміз:
Транзакцияны ашу... Клиент үшін кейбір операцияларды орындау - Толя Транзакцияны жабу....
Егер біз әдісімізге ерекше жағдайды қоссақ ( кенеттен операция сәтсіз аяқталады ):
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 көмегімен ішкі айнымалының мәнін орнатамыз - 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. Әдісте қайтаратын мән болған кезде if (returningValue != null) {
  2. Басқа қайтару мәні болмаған кезде {
@AfterThrowing(мән = "methodExecuting()", throwing = "ерекше жағдай") - қате болған жағдайда, яғни әдістен ерекшелік шығарылғанда іске қосылатын кеңес. Тиісінше, main пернесін іске қосу арқылы біз консольде кірудің бір түрін аламыз:
Әдісі - setValue, класстың - Main сәтті орындалды. - getValue, класстың - Main әдісі сәтті орындалды, орындалу нәтижесімен - <кейбір мән> Әдіс - checkValue, сыныптың - Main, ерекшелікпен әдеттен тыс тоқтатылды - java.lang.Exception Әдісі - негізгі, сынып-Негізгі, ерекшелікпен бұзылды - java.lang.Exception
Ерекше жағдайды өңдемегендіктен, біз оның стектрексін де аламыз: AOP дегеніміз не?  Аспектілі бағдарланған бағдарламалау негіздері – 5Ерекшеліктер және оларды өңдеу туралы мына мақалалардан оқи аласыз: Java-дағы ерекшеліктер және Ерекшеліктер және оларды өңдеу . Бүгін мен үшін барлығы осы. Бүгін біз AOP- пен таныстық , және сіз бұл аңның боялғандай қорқынышты емес екенін көрдіңіз. Барлығына сау бол!AOP дегеніміз не?  Аспектілі бағдарланған бағдарламалау негіздері – 6
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION