Heim  >  Artikel  >  Java  >  Detaillierte Erklärung von SpringAop in Java

Detaillierte Erklärung von SpringAop in Java

黄舟
黄舟Original
2017-10-08 09:34:091411Durchsuche

Ich habe in den letzten Tagen SpringAop studiert und einige Informationen im Internet gefunden. Dieser Link ist der Originallink http://www.cnblogs.com/xrq730/p/4919025.html

AOP

AOP (Aspektorientierte Programmierung), eine aspektorientierte Programmierung, kann als Ergänzung und Verbesserung von OOP (Objektorientierte Programmierung) bezeichnet werden. OOP führt Konzepte wie Kapselung, Vererbung und Polymorphismus ein, um eine Objekthierarchie einzurichten, die zur Simulation einer Sammlung öffentlicher Verhaltensweisen verwendet wird. OOP ermöglicht Entwicklern zwar die Definition vertikaler Beziehungen, eignet sich jedoch nicht für die Definition horizontaler Beziehungen, z. B. Protokollierungsfunktionen. Protokollierungscode ist häufig horizontal über alle Objekthierarchien verteilt und hat nichts mit der Kernfunktionalität des entsprechenden Objekts zu tun. Das Gleiche gilt für andere Codetypen, z. B. Sicherheit, Ausnahmebehandlung und transparente Persistenz Beim OOP-Design führt dies zur Duplizierung großer Codemengen und ist der Wiederverwendung verschiedener Module nicht förderlich.

Die AOP-Technologie ist genau das Gegenteil. Sie verwendet eine Technologie namens „Cross-Cutting“, um das Innere des gekapselten Objekts zu zerlegen und die öffentlichen Verhaltensweisen, die sich auf mehrere Klassen auswirken, in einem wiederverwendbaren Modul zu kapseln und es „Aspekt“ zu nennen ", das ist der Aspekt. Bei den sogenannten „Aspekten“ handelt es sich einfach um gekapselte Logik oder Verantwortlichkeiten, die nichts mit dem Geschäft zu tun haben, sondern von den Geschäftsmodulen gemeinsam aufgerufen werden, um die Codeduplizierung im System zu reduzieren, die Kopplung zwischen Modulen zu reduzieren und zu erleichtern zukünftige Bedienbarkeit und Wartbarkeit.

Mithilfe der „übergreifenden“ Technologie unterteilt AOP das Softwaresystem in zwei Teile: Kernanliegen und Übergreifende Anliegen. Der Hauptprozess der Geschäftsabwicklung ist das Kernanliegen, und der Teil, der wenig damit zu tun hat, ist das Querschnittsthema. Ein Merkmal übergreifender Anliegen besteht darin, dass sie häufig an mehreren Stellen im Kernanliegen auftreten und die Stellen grundsätzlich ähnlich sind, wie z. B. Autoritätsauthentifizierung, Protokolle usw. Die Rolle des AOP besteht darin, verschiedene Anliegen im System zu trennen und Kernanliegen von übergreifenden Anliegen zu trennen.

AOP-Kernkonzepte

1. Querschnittsthemen

Welche Methoden sollten abgefangen werden und wie man damit umgeht nach dem Abfangen? Diese Bedenken werden als Querschnittsprobleme bezeichnet

2. Die Klasse Aspekt

ist eine Abstraktion von Objekteigenschaften und der Aspekt ist eine Abstraktion von Querschnittsproblemen

3. Verbindungspunkt (Joinpoint)

Abgefangener Punkt, da Spring nur Verbindungspunkte vom Methodentyp unterstützt, sodass sich der Verbindungspunkt in Spring auf die abgefangene Methode bezieht. Tatsächlich ist der Verbindungspunkt immer noch ein Feld oder Konstruktor

4. Pointcut (Pointcut)

Definition des Abfangens des Verbindungspunkts

5. Hinweis (Hinweis)

Die sogenannte Benachrichtigung bezieht sich auf den Code, der nach dem Abfangen des Verbindungspunkts ausgeführt werden soll. Die Benachrichtigungen sind in fünf Kategorien unterteilt: Vor-, Nach-, Ausnahme-, End- und Umgebungsbenachrichtigungen

6. Zielobjekt

Agent Das Zielobjekt

7. Weben

Der Prozess der Anwendung von Aspekten auf das Zielobjekt und der Veranlassung der Erstellung des Proxy-Objekts

8. Einführung

Ohne den Code zu ändern, führen Sie einige Methoden oder Felder ein, die der Klasse während der Laufzeit

Springs Unterstützung für AOP-Unterstützung dynamisch hinzugefügt werden können

Der AOP-Proxy in Spring wird vom IOC-Container von Spring generiert und verwaltet, und seine Abhängigkeiten werden auch vom IOC-Container verwaltet. Daher kann der AOP-Proxy andere Bean-Instanzen im Container direkt als Ziele verwenden, und diese Beziehung kann durch die Abhängigkeitsinjektion des IOC-Containers bereitgestellt werden. Die Regeln von Spring zum Erstellen eines Proxys lauten:

1, Standardmäßig wird der dynamische Java-Proxy zum Erstellen eines AOP-Proxys verwendet, sodass ein Proxy für jede Schnittstelleninstanz

erstellt werden kann

2, Wenn die Klasse, die einen Proxy benötigt, keine Proxy-Schnittstelle ist, wechselt Spring zur Verwendung des CGLIB-Proxys, oder Sie können die Verwendung von CGLIB erzwingen

AOP-Programmierung ist tatsächlich Eine sehr einfache Angelegenheit. Bei der AOP-Programmierung müssen Mitglieder nur an drei Teilen teilnehmen:

1. Definieren Sie gemeinsame Geschäftskomponenten.

Geschäftskomponenten

3. Erweiterte Verarbeitung definieren ist eine Verarbeitungsaktion, die in das AOP-Framework für gewöhnliche Geschäftskomponenten eingebunden ist

Daher liegt der Schlüssel zur AOP-Programmierung darin, Einstiegspunkte und erweiterte Verarbeitung zu definieren Sobald die entsprechenden Einstiegspunkte und die erweiterte Verarbeitung definiert sind, generiert das AOP-Framework automatisch einen AOP-Proxy, das heißt: Proxy-Objekt-Methode = erweiterte Verarbeitung + Proxy-Objekt -Methode.

Das Folgende ist eine einfache Implementierung von AOP

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
            
</beans>

Bevor ich es erkläre, möchte ich eines erklären: Spring AOP zu verwenden, um den Code erfolgreich auszuführen Es reicht nicht aus, nur das von Spring für Entwickler bereitgestellte JAR-Paket zu verwenden: 1 🎜> Beginnen wir mit der XML-Implementierung mithilfe von Spring AOP. Definieren Sie zunächst eine Schnittstelle:

Definieren Sie zwei Schnittstellenimplementierungsklassen:

Übergreifende Bedenken, hier ist die Druckzeit:

1 public interface HelloWorld
2 {
3     void printHelloWorld();
4     void doPrint();
5 }
Mit diesen drei Klassen können Sie ein einfaches Spring AOP implementieren. Schauen Sie sich die Konfiguration von aop.xml an

public class HelloWorldImpl1 implements HelloWorld
{
    public void printHelloWorld()
    {
        System.out.println("Enter HelloWorldImpl1.printHelloWorld()");
    }
    
    public void doPrint()
    {
        System.out.println("Enter HelloWorldImpl1.doPrint()");
        return ;
    }
}
Schreiben Sie eine Hauptfunktion, um sie aufzurufen:
public class HelloWorldImpl2 implements HelloWorld
{
    public void printHelloWorld()
    {
        System.out.println("Enter HelloWorldImpl2.printHelloWorld()");
    }
    
    public void doPrint()
    {
        System.out.println("Enter HelloWorldImpl2.doPrint()");
        return ;
    }
}

Das laufende Ergebnis ist:
public class TimeHandler
{
    public void printTime()
    {
        System.out.println("CurrentTime = " + System.currentTimeMillis());
    }
}


CurrentTime = 1446129611993Enter HelloWorldImpl1.printHelloWorld()
CurrentTime = 1446129611993CurrentTime = 1446129611994Enter HelloWorldImpl1.doPrint()
CurrentTime = 1446129611994CurrentTime = 1446129611994Enter HelloWorldImpl2.printHelloWorld()
CurrentTime = 1446129611994CurrentTime = 1446129611994Enter HelloWorldImpl2.doPrint()
CurrentTime = 1446129611994

看到给HelloWorld接口的两个实现类的所有方法都加上了代理,代理内容就是打印时间

基于Spring的AOP使用其他细节

1、增加一个横切关注点,打印日志,Java类为:

public class LogHandler
{
    public void LogBefore()
    {
        System.out.println("Log before method");
    }
    
    public void LogAfter()
    {
        System.out.println("Log after method");
    }
}

aop.xml配置为:

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
        
        <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" />
        <bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" />
        <bean id="timeHandler" class="com.xrq.aop.TimeHandler" />
        <bean id="logHandler" class="com.xrq.aop.LogHandler" />
        
        <aop:config>
            <aop:aspect id="time" ref="timeHandler" order="1">
                <aop:pointcut id="addTime" expression="execution(* com.xrq.aop.HelloWorld.*(..))" />
                <aop:before method="printTime" pointcut-ref="addTime" />
                <aop:after method="printTime" pointcut-ref="addTime" />
            </aop:aspect>
            <aop:aspect id="log" ref="logHandler" order="2">
                <aop:pointcut id="printLog" expression="execution(* com.xrq.aop.HelloWorld.*(..))" />
                <aop:before method="LogBefore" pointcut-ref="printLog" />
                <aop:after method="LogAfter" pointcut-ref="printLog" />
            </aop:aspect>
        </aop:config>
</beans>

测试类不变,打印结果为:

CurrentTime = 1446130273734
Log before method
Enter HelloWorldImpl1.printHelloWorld()
Log after method
CurrentTime = 1446130273735

CurrentTime = 1446130273736
Log before method
Enter HelloWorldImpl1.doPrint()
Log after method
CurrentTime = 1446130273736

CurrentTime = 1446130273736
Log before method
Enter HelloWorldImpl2.printHelloWorld()
Log after method
CurrentTime = 1446130273736

CurrentTime = 1446130273737
Log before method
Enter HelloWorldImpl2.doPrint()
Log after method
CurrentTime = 1446130273737

要想让logHandler在timeHandler前使用有两个办法:

(1)aspect里面有一个order属性,order属性的数字就是横切关注点的顺序,数字越大执行越靠后,后置通知相反。

(2)把logHandler定义在timeHandler前面,Spring默认以aspect的定义顺序作为织入顺序

2、我只想织入接口中的某些方法

修改一下pointcut的expression就好了:

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
        
        <bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" />
        <bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" />
        <bean id="timeHandler" class="com.xrq.aop.TimeHandler" />
        <bean id="logHandler" class="com.xrq.aop.LogHandler" />
        
        <aop:config>
            <aop:aspect id="time" ref="timeHandler" order="1">
                <aop:pointcut id="addTime" expression="execution(* com.xrq.aop.HelloWorld.print*(..))" />
                <aop:before method="printTime" pointcut-ref="addTime" />
                <aop:after method="printTime" pointcut-ref="addTime" />
            </aop:aspect>
            <aop:aspect id="log" ref="logHandler" order="2">
                <aop:pointcut id="printLog" expression="execution(* com.xrq.aop.HelloWorld.do*(..))" />
                <aop:before method="LogBefore" pointcut-ref="printLog" />
                <aop:after method="LogAfter" pointcut-ref="printLog" />
            </aop:aspect>
        </aop:config>
</beans>

表示timeHandler只会织入HelloWorld接口print开头的方法,logHandler只会织入HelloWorld接口do开头的方法

3、强制使用CGLIB生成代理

前面说过Spring使用动态代理或是CGLIB生成代理是有规则的,高版本的Spring会自动选择是使用动态代理还是CGLIB生成代理内容,当然我们也可以强制使用CGLIB生成代理,那就是5f4edcee1f0c5735c643ff3ca537e591里面有一个"proxy-target-class"属性,这个属性值如果被设置为true,那么基于类的代理将起作用,如果proxy-target-class被设置为false或者这个属性被省略,那么基于接口的代理将起作用。

Das obige ist der detaillierte Inhalt vonDetaillierte Erklärung von SpringAop in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn