JavaRush /Kurslar /All lectures for AZ purposes /Əməkdəlik Abstraksiyası Anlayışı

Əməkdəlik Abstraksiyası Anlayışı

All lectures for AZ purposes
Səviyyə , Dərs
Mövcuddur

Spring-in əməkdəlik abstraksiyasını anlamağın açarı, əməkdəlik strategiyası anlayışıdır. Əməkdəlik strategiyası TransactionManager, xüsusilə də org.springframework.transaction.PlatformTransactionManager interfeysinin vasitəsilə - imperativ əməkdəliklərin idarə olunması, həmçinin org.springframework.transaction.ReactiveTransactionManager interfeysinin vasitəsilə - reaktiv əməkdəliklərin idarə olunması ilə müəyyənləşdirilir. Növbəti kod parçası PlatformTransactionManager API interfeysinin müəyyənləşdirilməsini göstərir:

public interface PlatformTransactionManager extends TransactionManager {
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
    void commit(TransactionStatus status) throws TransactionException;
    void rollback(TransactionStatus status) throws TransactionException;
}

Bu, əsasən xidmət təminatçısı interfeysidir (SPI), baxmayaraq ki, onu proqramlı olaraq tətbiq kodundan istifadə etmək olar. PlatformTransactionManager interfeys olduğundan, onu asanlıqla imitasiya obyekti və ya stubları kimi həyata keçirmək olar. O, JNDI kimi bir axtarış strategiyasına bağlı deyil. PlatformTransactionManagerin tətbiqləri Spring Framework IoC konteynerində hər hansı başqa obyekt (və ya bean) kimi müəyyənləşdirilir. Bu yalnız bir üstünlük Spring Framework-dən istifadə edərək əməkdəlikləri layiqli abstraksiya edir, hətta JTA ilə işləsəz belə. Əməkdəlik kodunu test etmək daha asan olur, əgər o JTA-dan birbaşa istifadə etməzsə, əlbəttə.

Yenidən Spring-in fəlsəfəsinə uyğun olaraq, TransactionException interfeysinin hər hansı bir metodundan atıla bilən istisna istifadəçinin seçiminə buraxılmışdır (yəni java.lang.RuntimeException sinfini genişləndirir). Əməkdəlik infrastrukturunda olan nasazlıqlar demək olar ki, həmişə kritikdir. İstisna hallarda, tətbiq kodu həqiqətən əməkdəliyin nasazlığından bərpa ola bilər, tətbiq inkişafçısı hələ də TransactionExceptionni tutub idarə edə bilər. Əsas məqam odur ki, inkişafçılar bunu məcburiyyət olmadan edə bilər.

getTransaction(..) metodu TransactionDefinition parametrinə əsasən TransactionStatus obyektini qaytarır. Qaytarılan TransactionStatus yeni əməkdəliyi təmsil edə bilər və ya cari çağırış silsiləsində müvafiq bir əməkdəlik varsa mövcud əməkdəliyi təmsil edə bilər. Sonuncu halda, Java EE əməkdəlik kontekstləri ilə olduğu kimi, TransactionStatus icra axını ilə əlaqələndirilir.

Spring Framework 5.2 versiyasından etibarən, Spring həmçinin reaktiv tipli və ya Kotlin koroutines istifadə edən reaktiv tətbiqlər üçün əməkdəlik idarəetmə abstraksiyası təqdim edir. Növbəti kod parçası org.springframework.transaction.ReactiveTransactionManager ilə müəyyənləşdirilmiş əməkdəlik strategiyasını göstərir:

public interface ReactiveTransactionManager extends TransactionManager {
    Mono<ReactiveTransaction> getReactiveTransaction(TransactionDefinition definition) throws TransactionException;
    Mono<Void> commit(ReactiveTransaction status) throws TransactionException;
    Mono<Void> rollback(ReactiveTransaction status) throws TransactionException;
}

TransactionDefinition interfeysi müəyyənləşdirir:

  • Yayılma: Adətən, əməkdəlik mövcudluq sahəsindəki bütün kod bu əməkdəlikdə icra olunur. Lakin, əməkdəlik metodu, artıq mövcud bir əməkdəlik konteksti varsa necə davranacağı üçün loqik təyin etmək olar. Məsələn, kodun icrası mövcud əməkdəlikdə (adi hal) davam edə bilər və ya mövcud əməkdəlik dayandırılıb, yeni bir əməkdəlik yaradıla bilər. Spring, EJB-dən tanış olan əməkdəlik yayılma növlərini təklif edir. Spring-də əməkdəlik yayılması semantikası ilə tanış olmaq üçün "Əməkdəlik Yayılması" bölməsinə baxın.

  • İzolasiya: Bu əməkdəliyin digər əməkdəliklərin işindən hansı dərəcədə təcrid edilmişdir. Məsələn, bu əməkdəlik digər əməkdəliklərdən təsdiq edilməmiş qeydləri görə bilərmi?

  • Gözləmə vaxtı: Əməkdəliyin icra müddəti neçə vaxt davam edəcək və əsas əməkdəlik infrastrukturu tərəfindən avtomatik olaraq geri çevriləcək.

  • Yalnız oxumaq üçün status: Kodunuzun məlumatları oxuyacağı, lakin onları dəyişdirə bilməyəcəyi rejimdə əməkdəlikdən istifadə edilə bilər. Yalnız oxumaq üçün əməkdəliklər bəzi hallarda, məsələn, Hibernate istifadə edirsinizsə, optimizasiya kontekstində faydalı ola bilər.

Bu parametrlər standart əməkdəlik anlayışlarını əks etdirir. İstifadəçilərin əməkdəlik təcrid səviyyələri və digər əsas əməkdəlik anlayışları haqqında daha çox məlumat əldə etmək üçün mənbələrə müraciət etmək zərurəti ola bilər. Bu anlayışları anlamaq, Spring Framework və ya hər hansı əməkdəlik idarəetmə həllindən istifadə etmək üçün lazımdır.

TransactionStatus interfeysi əməkdəlik koduna heç bir maneə olmadan əməkdəliyin icrasını idarə etmək və əməkdəliyin statusunu sorğulamaq imkanı verir. Bu konsepsiyalar tanış olmalıdır, çünki onlar bütün əməkdəlik API-ləri üçün ümumidir. Növbəti kod parçası TransactionStatus interfeysini göstərir:

public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {
    @Override
    boolean isNewTransaction();
    boolean hasSavepoint();
    @Override
    void setRollbackOnly();
    @Override
    boolean isRollbackOnly();
    void flush();
    @Override
    boolean isCompleted();
}

Spring-də əməkdəlik idarəetməsinin hansı üsulunu seçirsinizsə - deklarativ və ya proqramlı - doğru TransactionManagerin tətbiqini müəyyənləşdirmək mütləq zəruridir. Adətən, bu tətbiq asılılıqların inyeksiyası vasitəsilə müəyyənləşdilir.

TransactionManager tətbiqləri adətən onların işlədikləri mühiti, məsələn, JDBC, JTA, Hibernate və s., bilməyi tələb edir. Növbəti nümunələr göstərir ki, adi JDBC vasitəsilə PlatformTransactionManager lokal həyata keçirilməsi necə müəyyən edilə bilər.

JDBC DataSourceni aşağıdakı bənzər bir bean yaradırıqsa müəyyən edə bilərsiniz:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
</bean>

Sonra əlaqəli PlatformTransactionManager bean-i DataSource müəyyənləşdirilməsinə istinadla təmin edilir. Müəyyənləşdirmə aşağıdakı nümunədəki kimi olmalıdır:

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

Əgər Java EE konteynerində JTA istifadə edirsinizsə, Spring-dən JtaTransactionManager ilə birlikdə JNDI vasitəsilə əldə edilmiş konteyner DataSource istifadə edirsinizsə, JTA və JNDI-nin axtarışı versiyası aşağıdakı kimi görünəcəyi göstərilir:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/jee
        https://www.springframework.org/schema/jee/spring-jee.xsd">
    <jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/>
    <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
    <!-- digər <bean/--> müəyyənləşdirmələri -->
</beans>

JtaTransactionManager DataSource (və ya hər hansı digər xüsusi resurslar) haqqında bilməyə ehtiyac yoxdur, çünki o, konteynerin qlobal əməkdəlik idarəetmə infrastrukturundan istifadə edir.

Yuxarıda göstərilən dataSource bean-i müəyyənləşdirməsində <jndi-lookup/> etiketi jee namespacesindən istifadə olunur. Daha ətraflı məlumat üçün baxın "JEE Şeması" bölməsinə.
Əgər JTA istifadə edirsinizsə, əməkdəlik manogerinin müəyyənləşdirməsi yeknəsək olmalıdır, məlumat əldə etmə texnologiyasının istifadə edilib-edilməyəcəyi əhəmiyyətli deyil - JDBC, Hibernate, JPA və ya digər dəstəklənən texnologiyalar. Bu, JTA əməkdəliklərinin qlobal əməkdəliklər olduğu üçün hər hansı bir əməkdəlik resursunu iştirak etdirə bilməsi ilə əlaqədardır.

Hər hansı bir təyin edilmiş əməkdəlik dəyərləri dəsti ilə Spring tətbiq kodunu dəyişmək lazım deyil. Əməkdəlik idarəetmə üsulunu dəyişdirmək, təkcə konfiqurasiyanı dəyişdirərək, hətta bu dəyişikliyin lokaldan qlobal əməkdəliklərə keçməsi olsa belə, mümkündür.

Hibernate Əməkdəliklərini Konfiqurasiya Etmək

Hibernate-dən lokal əməkdəlikləri asanlıqla istifadə etmək də mümkündür, növbəti nümunələrdə göstərildiyi kimi. Bu halda, tətbiq kodunuz Hibernate-dən Session obyektlərini almaq üçün istifadə edə biləcəyiniz LocalSessionFactoryBean müəyyənləşdirməlisiniz.

Yerel JDBC nümunəsində göstərildiyi kimi DataSource bean-i müəyyənləşdirməsi ilə oxşardır, dolayısıyla növbəti nümunələrdə göstərilmir.

Əgər məlumat mənbəyi DataSourcenin axtarışı (hər hansı bir qeyri-JTA əməkdəlik manoqeriylə birlikdə) JNDI vasitəsilə həyata keçirilirsə və idarəetmə Java EE vasitəsilə həyata keçirilirsə, o qeyri-əməkdəlik olmalıdır, çünki Spring Framework (və ya Java EE konteyneri deyil) əməkdəlikləri idarə edir.

Bu halda, txManager bean-i HibernateTransactionManager-nin tipinə malikdir. Eynilə DataSourceTransactionManager-nin DataSource-yə istinadlara ehtiyacı olduğu kimi, HibernateTransactionManager-nin SessionFactory-yə istinadlara ehtiyacı var. Növbəti nümunədə sessionFactorytxManager bean-ləri elan edilib:

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mappingResources">
        <list>
            <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect=${hibernate.dialect}
        </value>
    </property>
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

Əgər Hibernate və JTA ilə idarə olunan konteyner Java EE əməkdəliklərini istifadə edirsinizsə, əvvəlki JTA ilə JDBC nümunəsində olduğu kimi eyni JtaTransactionManagerdən istifadə etməlisiniz, bu növbəti nümunədə göstərilmişdir. Hibernate'in JTA-dan koordinasiya edicisi və bəlkə də bağlantı azadlıq rejimi konfiqurasiyası vasitəsi ilə xəbərdar olması tövsiyə olunur:

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mappingResources">
        <list>
            <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect=${hibernate.dialect}
            hibernate.transaction.coordinator_class=jta
            hibernate.connection.handling_mode=DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT
        </value>
    </property>
</bean>
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

Və ya eyni standart dəyərləri təmin etmək üçün LocalSessionFactoryBeanə JtaTransactionManager yollaya bilərsiniz:

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mappingResources">
        <list>
            <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect=${hibernate.dialect}
        </value>
    </property>
    <property name="jtaTransactionManager" ref="txManager"/>
</bean>
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION