Spring study notes (b) - Spring AOP programming

Spring AOP programming

Software system some of the features may be applied to multiple places in the program, these functions are called crosscutting concerns, (cross-cutting concern)but in the development process, you do not want in specific business logic to call these crosscutting concerns clear , the crosscutting concerns of business logic separate domain idea, oriented programming (AOP 编程).

1. What is the Aspect Oriented Programming

The figure shows a typical application is divided into module development, the core function of each module is to provide services for a particular business, but these modules require similar auxiliary functions, such as security and transaction management.

If you want to reuse common functionality, the most common object-oriented technology is inherited or is commissioned , but if you use the same base class throughout the application, inheritance often leads to a vulnerable target system; commissioned may need to delegate object complex It calls.

By programming Spring AOP can be implemented in a common place defined functions, but without modifying the code and explicitly called, the definition of this function by way of a declaration to be how , where , and when to use these functions . Crosscutting concerns can be modularized into special classes, which are called facets. This has two advantages:

  1. Each point of interest are concentrated in one place, rather than scattered to the extra code;
  2. Business logic module is more simple;

2, AOP term

2.1, notice (Advice)

In AOP programming, work section is called the notification that defines cut what and when to use, in addition to section describes work to be done, notice also addresses when to perform . In Spring AOP programming, notice the following five types:

  1. Pre-notification (Before): call notification function before the target method is called.
  2. After returning advice (After): call notification after completion of the target method can pass, do not care about the method of output ;
  3. A return notification (After-returning): call completion notification after the target method can pass;
  4. Exception notification (After-throwing): notification when the target method invocation ran an exception;
  5. Perform custom behavior after the notification method wrapped notified, before being notified method calls and call: Around advice (Around).

2.2, the connection point (Join point)

The existence of local applications may notice many applications, these places are called connection point. Is the point of attachment can be inserted in the course of the execution of a cut point. When this point can make the call method throws an exception. These codes can be cut points into the normal flow of application and add new behavior. Briefly, the connection point is that the program can be enhanced method.

2.3, tangent point (Pointcut)

A connecting section does not need to notify all the application points, the connection point tangent point help narrow the scope of the notification section. Notification defined section of what and when , on the definition of the cut-off point where . Definition of the tangent point would match notification to be woven into one or more connection points. In short, the cut-off point is the actual method of strengthening the actual development process is.

2.3.1, the preparation of the tangent point

To illustrate Spring facets, we need to define the cut point cut in. For this purpose, the definition of a Performanceclass:

package com.aop;

public class Performance {
    public void perform() {
        System.out.println("ready to perform ... ");
    }
}

If at this time you want to write a Performanceclass perform()method trigger a notification, you need to write an expression of a cut-off point, this expression can be set when the perform()call triggers a notification when the method is executed.

execution(* com.aop.Performance.perform(..))

We use the execution()pointer to select Performnacethe perform()method, the method of expression ** to start number "*" indicates that the method returns a value of any type. Then specify the perform()fully qualified class name and a method name of the method belongs. In the process parameters, used (..)to represent any parameter. **

2.4, section (Aspect)

Section is a collection of notification and cut-off point, and the point of tangency notice together define the entire contents of the section.

2.5, is introduced (Introduction)

Is introducing an enhanced level class, it allows us to add a new method or property to an existing class.

2.6, weaving (Weaving)

Weaving section is to be applied to the target object and create a new proxy object of the process.

3, Spring AOP support programming

Currently, Spring provides a simple and clean aspect-oriented programming. The introduction of a simple declarative AOP and annotation-based AOP. By the Spring aop namespace can be converted to a pure POJO section.

By proxy class wrapping section, the cut in the run Spring woven into Spring managed bean, as shown above, the proxy class encapsulates the target class, and to intercept calls to the notification method, then forwards the call to the real target bean. When the proxy intercepts calls to the method, before calling the target bean method performs logic section.

As shown below: In this case Emperor proxy class as the class, this time need Emperor Shi Qin Feizi business needs it, informing the proxy class through the business logic, the proxy class enhancements Shi Qin service occurs before and after the occurrence and, as in a notice before concubine Shi Qin bathing needs, other things like makeup. Then take a concubine to the emperor, the emperor Shi Qin execute business needs. End business logic execution, was told proxy class eunuch Shi Qin Emperor proxy class ended, the concubine back to the original place. In this procedure, the emperor Shi Qin business logic for the core business logic, Shi Qin other relevant business logic functions and methods to the Agent class to complete. Before being executed the proxy class service logic, to perform the method of the proxy class.

3.1, AOP based on a simple declarative programming

If you do not want in the source code for AspectJ annotation written into the code, you can use Spring XML configuration files declaratively section.

3.1.1, Spring's AOP configuration elements

AOP configuration elements use
<aop:advisor> AOP defined notifier
<aop:after> After advice AOP definitions, methods, regardless of whether or not notified to be executed.
<aop:after-returning> AOP defined return notice.
<aop:after-throwing> AOP defined exception notification.
<aop:around> Defined AOP around advice.
<aop:before> AOP pre-defined notification.
<aop:aspect> Defining aspects.
<aop:config> Top of AOP configuration elements, most of the <aop:*>elements must be contained within the element.
<aop:pointcut> Define a tangent point
<aop:declare-parents> In a transparent manner for the object to be notified introduce additional interfaces.
<aop:aspectj-autoproxy> @AspectJ enable annotation-driven section.

3.1.2, written notice

package com.aop;

public class Audience {

    public void silenceCellPhones() {
        System.out.println("Please, silencing cell phones ...");
    }
    
    public void takeSeats() {
        System.out.println("Please, Taking seats ...");
    }
    
    public void applause() {
        System.out.println("CLAP CLAP CLAP ...");
    }
    
    public void demandRefund() {
        System.out.println("Demanding a refund ...");
    }
}

In this case, Audienceclass and there is nothing about, it is a plain Java class contains several methods. By the Spring applicationContext.xmlconfiguration file, Audienceclass registration for the Spring application context bean, bean and then select the cut-off point, you can make Audiencenotification class called AOP.

1, registered Spring application context
<?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:context="http://www.springframework.org/schema/context"
    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.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    
    <context:annotation-config/>        
    <bean id="audience" class="com.aop.Audience"></bean>
    <bean id="performance" class="com.aop.Performance"></bean>
</beans>
2, the cut point selected in the bean

About Spring AOP configuration elements of the first things to note is that most of the AOP configuration elements must be in <aop:config>use within the context of the element.

<?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:context="http://www.springframework.org/schema/context"
    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.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    
<context:annotation-config/>        

    <bean id="audience" class="com.aop.Audience"></bean>
    <bean id="performance" class="com.aop.Performance"></bean>
    <aop:config>
        <!--
            定义切点: 
                配置需要进行增强的方法
         -->
        <aop:pointcut expression="execution(* com.aop.Performance.perform(..))" id="enhancerPerform" />
    </aop:config>
</beans>

3.1.3, the statement front, rear and throws advice

In <aop:config>elements, we can declare one or more notifier, cut or cut-off point.

<aop:config>
        <!--
            定义切点: 
                配置需要进行增强的方法
         -->
    <aop:pointcut expression="execution(* com.day02.aop.Performance.perform(..))" id="enhancerPerform" />
    <aop:aspect ref="audience">
            <!-- 定义前置通知 -->
        <aop:before method="silenceCellPhones" pointcut="execution(* com.day02.aop.Performance.perform(..))"/>
        <aop:before method="takeSeats" pointcut="execution(* com.day02.aop.Performance.perform(..))"/>
            <!-- 定义返回通知 -->
        <aop:after-returning method="applause" pointcut="execution(* com.day02.aop.Performance.perform(..))"/>
            <!-- 定义异常通知 -->
        <aop:after-throwing method="demandRefund" pointcut="execution(* com.day02.aop.Performance.perform(..))"/>
    </aop:aspect>
</aop:config>

By using <aop:aspect>elements declares a simple cut, refelement references a POJO bean, the bean implementation section of the function. refElements referenced bean provides role notification to the called method in the section. This section applies four different notification. Two <aop:before>elements define a pre-notification method called before the cut-off point matching method of execution - that is, the Audience bean takeSeats()and silenceCellPhones()methods (declared by the method attribute). <aop:after-returning>Element defines a return (after-returning) notification, after the tangent point matching method call and then call the applaud()method. Similarly, the <aop:after-throwing>element defines an exception (after-throwing) notice, throw any exception if the method of execution to match, both will call the demandRefund()method.

3.1.4, the statement around advice

Front and rear with respect to the notification, the notification can be done around the pre-notification, and the same functionality achieved after advice, and only needs to be implemented in a process. Because the entire notification logic is implemented within a method.

In Audienceadd class watchPerformance()methods to achieve the performance and turn off the cell phone technology applause of the audience before entering the functional requirements in the process.

package com.day02.aop;

import org.aspectj.lang.ProceedingJoinPoint;

public class Audience {

    public void watchPerformance(ProceedingJoinPoint joinPoint) {
        try {
            // 完成前置通知的功能
            silenceCellPhones();
            takeSeats();
            joinPoint.proceed();
            // 完成后置通知的功能
            applause();
        } catch (Throwable e) {
            // 实现异常通知的功能
            demandRefund();
        }
    }
}

You can see, pre-notification achieve this effect with the previous notification, the effect of the post-notification and exception notification with the use of the same, but through the use of around advice, you can get them in the same method. About Surround notification in the notification, received ProceedingJoinPointupon the type of parameters, the type of object that can be invoked method to be notified in the notification, the notification method can do anything, when you want to control methods notified to the , calling ProceedingJoinPointthe proceed()method can be.

In the section of the audience, the watchPerformance()method includes all the features before four notification method. However, all the methods is found in one method, so this method is also responsible for its own exception handling. Statement Around advice and other statements type of notification is not much difference. We need to do is use the <aop:around>element.

<aop:config>
    <!-- 定义切点: 配置需要进行增强的方法 -->
    <aop:pointcut expression="execution(* com.day02.aop.Performance.perform(..))" id="enhancerPerform" />
    
    <aop:aspect ref="audience">
        <aop:around method="watchPerformance" pointcut-ref="enhancerPerform"/>
    </aop:aspect>
</aop:config>

Like other XML elements of the same notification, <aop:around>specify the name of a point cut and a notification method, method attribute is set for the cut-point watchPerformance()method.

3.1.5 for notification delivery parameters

In the above case, the cut are relatively simple, in addition to the around advice, written notice there are not any parameters. However, if the method does have notified section parameters, cut access to and use of the notification method parameters are passed to it?

<?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:context="http://www.springframework.org/schema/context"
    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.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd">

    <context:annotation-config />
    <!-- 启用@AspectJ注解驱动的切面 -->
    <aop:aspectj-autoproxy />
    
    <bean id="blankDiscAspectJ" class="com.aop.config.BlankDiscAspectJ"></bean>
    <bean id="blankDisc" class="com.aop.config.BlankDisc">
        <property name="discTitle" value="张学友怀旧金曲"/>
        <property name="artist" value="张学友"/>
        <property name="tracks">
            <list>
                <value>爱你痛到不知痛</value>
                <value>如果这都不算爱</value>
                <value>寂寞的男人</value>
                <value>结束不是我要的结果</value>
                <value>你说的</value>
            </list>
        </property>
    </bean>
    <aop:config>
        <aop:aspect ref="blankDiscAspectJ">
            <aop:pointcut expression="execution(* com.aop.config.BlankDisc.playTrackById(int)) and args(trackId)" id="playByTrackId"/>
            <aop:after-returning method="PlayTrack" pointcut-ref="playByTrackId"/>
        </aop:aspect>
    </aop:config>
</beans>

Listing: BlankDisc class

package com.aop.config;

import java.util.List;

public class BlankDisc {
    private List<String> tracks;
    
    public List<String> getTracks() {
        return tracks;
    }
    public void setTracks(List<String> tracks) {
        this.tracks = tracks;
    }
    
    public void playTrackById(int trackId) {
        System.out.println("请播放曲目:" + trackId);
    }
}

In the BlankDiscpresence of the class playTrackById(int trackId)method to choose the next song to play the tape in the specified table by passing parameters, you can see that we used the same front and AOP namespace XML elements, they will be declared as POJO section, but the only difference expression that is tangent point contains a parameter. By and args(参数名称)the method of notification is passed to this parameter.

<aop:pointcut expression="execution(* com.aop.config.BlankDisc.playTrackById(int)) and args(trackId)" id="playByTrackId"/>

The above configuration, the notification method can be the trackIdparameters passed to the method section.

Listing: BlankDiscAspectJ class, receiving notification parameter method

package com.aop.config;

import javax.annotation.Resource;

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class BlankDiscAspectJ {

    @Resource(name = "blankDisc")
    private BlankDisc blankDisc;

    public void PlayTrack(int trackId) {
        int totalTracks = blankDisc.getTracks().size();
        if (trackId < 0) {
            System.out.println("输入的序号不合法 ... ");
        } else {
            if (trackId > totalTracks) {
                System.out.println("输入的序号不合法 ... ");
            } else {
                System.out.println("正在播放曲目:《" + blankDisc.getTracks().get(trackId - 1) + "》");
            }
        }
    }
}

Listing: Test parameters are acquired notification methods

package com.aop.config;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestBlankDisc {
    
    @Resource(name="blankDisc")
    private BlankDisc blankDisc;
    
    @Test
    public void testDemo01() {
        blankDisc.playTrackById(3);
        // 运行结果:
        // 请播放曲目:3
        // 正在播放曲目:《寂寞的男人》
    }
}

3.2, annotation-based programming AOP

Use annotations to Spring AOP AspectJ programming is a key feature introduced. AspectJ annotation-oriented model can be very simple by any small amount of notes to be converted to class section.

3.2.1, writing aspects

If you need to use annotations way to develop AOP, you first need in the Spring configuration file to enable @AspectJannotation-driven section .

<!-- 使用@Aspect注解驱动的切面 -->
<aop:aspectj-autoproxy />

From the point of view of the performance, the audience is very important. But for the performance of the function itself is concerned, it is not core, but a separate concern. Therefore, the audience is defined as a section, and apply it to is the more sensible approach on the show.

Listing: Performance classes: Class Performance

package com.aop;

public class Performance {

    public void perform() {
        System.out.println("演出开始 ...");
    }
}

Listing: AudienceAnno categories: viewers watch the show section

package com.aop.config;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class AudienceAnno {

    // 前置通知——表演之前
    @Before("execution(* com.aop.Performance.perform(..))")
    public void silenceCellPhones() {
        System.out.println("将手机调至静音...");
    }
    // 前置通知——表演之前
    @Before("execution(* com.aop.Performance.perform(..))")
    public void takeSeats() {
        System.out.println("请按座位号入座...");
    }
    // 返回通知——表演之后
    @AfterReturning("execution(* com.aop.Performance.perform(..))")
    public void applause() {
        System.out.println("节目表演精彩,鼓掌...");
    }
    // 异常通知——表演失败之前
    @AfterReturning("execution(* com.aop.Performance.perform(..))")
    public void demandRefund() {
        System.out.println("演出出现问题,赶紧退票...");
    }
}

AudienceAnnoClass uses @Aspectannotate been labeled, the annotation indicates that AudienceAnnomore than just a POJO, is also a section. AudienceAnnoMethods in the class are using annotations to define the specific behavior of the section.

AudienceAnnoThere are four methods, namely a definition of what the audience watching the show might be made:

  1. silenceCellPhones(): Before the show, the audience will mute the phone;
  2. takeSeats(): Before the show, the audience seated;
  3. applause(): After the show, if brilliant performances, the audience applauded;
  4. demandRefund(): Abnormal performance, the audience did not meet expectations, the audience requirements refund;

3.2.2, Spring in AspectJ annotation types

In AspectJ, it provides five the following annotation to define the notification:

Note the solution Notice
@After Notification method will be called after the target method returns or throws an exception
@AfterReturning Notification method will be called after the target method returns
@AfterThrowing After the notification method will throw an exception in the target method invocation
@Around Method notification method will encapsulate certain
@Before Notification method will be executed before the target method invocation

AudienceAnnoIt uses three of the previous five notes. takeSeats()And silenceCellPhones()we have used the @Beforenotes, indicating that they should be called before the show began. applause()The method uses @AfterReturningnotes, it will be called after the show successful return. demandRefund()Method to add a @AfterThrowingcomment, suggesting that it will be executed after throwing an exception.

3.2.3, using @Pointcut notes sound Mingqie point expression

In AudienceAnnoall annotations gave a given pointcut expression as its value, while the four cut-point representation methods are the same. But in the actual development, we can set a different tangent point expression. But in small projects, you will find as long as the Performanceclass perform()is triggered when the method executes and calls AudienceAnnothe class method that is relevant notification. It found that AudienceAnnousing the same cut point expression four times, in the actual development process, you can use @Pointcutto define the cut-off point annotation, and then every time when you need to refer to the cut-off point.

Point cut by @Pointcut annotation expression frequently used statement: Listing

package com.aop.config;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class AudienceAnno {
    
    @Pointcut("execution(* com.aop.Performance.perform(..))")
    public void performance() {}

    // 前置通知——表演之前
    @Before("performance()")
    public void silenceCellPhones() {
        System.out.println("前置通知---将手机调至静音...");
    }
    // 前置通知——表演之前
    @Before("performance()")
    public void takeSeats() {
        System.out.println("前置通知---请按座位号入座...");
    }
    // 返回通知——表演之后
    @AfterReturning("performance()")
    public void applause() {
        System.out.println("返回通知---节目表演精彩,鼓掌...");
    }
    // 异常通知——表演失败之前
    @AfterThrowing("performance()")
    public void demandRefund() {
        System.out.println("异常通知---演出出现问题,赶紧退票...");
    }
}

In AudienceAnnothe, performance()method of the @Pointcutannotation, which is referred to as a cut point set expression. In this method the actual content is not important, in fact, the method itself is just a logo, for @Pointcutnotes attached. Note that: In addition to notes and no practical significance performance()than the method, AudienceAnnoclass is still a POJO, we can call its methods like any other Java classes that.

3.2.4 to create around advice

Around advice allows business logic to be executed by the target method to be notified totally wrapped up, actually like to write pre-notification and post a notice at the same time notification method.

Listing: AudienceAnno class, created around advice

package com.aop.config;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class AudienceAnno {

    @Pointcut("execution(* com.aop.config.Performance.perform(..))")
    public void performance() {
    }
    
    /**
     * 之前的通知方法略
     */

    // 环绕通知方法
    @Around("performance()")
    public void watchPerformance(ProceedingJoinPoint joinPoint) {
        try {
            // 调用之前前置通知
            takeSeats();
            silenceCellPhones();
            joinPoint.proceed();
            // 调用之前的返回通知
            applause();
        } catch (Throwable e) {
            // 调用之前的异常通知
            demandRefund();
        }
    }
}

As used herein the @Aroundannotation, the annotation indicates that the watchPerformance()method will as a performance()cut-off point around advice. By accepting ProceedingJoinPointthe type as a parameter, by the type of object proceed()methods to call the methods to be notified.

3.2.5, processing parameters notification

Remove around advice, written before the notification method are not concerned about the situation to the method parameters. How to cut the parameters passed to the method of notification cut it? As Listing provided by case:

Listing: BlankDisc categories:

package com.aop.config;

import java.util.List;

public class BlankDisc {
    
    private List<String> tracks;
    
    public List<String> getTracks() {
        return tracks;
    }
    public void setTracks(List<String> tracks) {
        this.tracks = tracks;
    }
    
    public void playTrackById(int trackId) {
        System.out.println("请播放曲目:" + trackId);
    }
}

In BlankDiscclass playTrackById()method, there is a tape in many songs, the song number is passed to this method as a parameter, and having a specified playback tape index location of the song.

Listing: BlankDiscAspectJ class, receiving notification parameter method

package com.aop.config;

import javax.annotation.Resource;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class BlankDiscAspectJ {
    
    @Resource(name="blankDisc")
    private BlankDisc blankDisc;
    
    @Pointcut("execution (* com.aop.config.BlankDisc.playTrackById(int)) && args(trackId)")
    public void playTrackById(int trackId){}
    
    @AfterReturning("playTrackById(trackId)")
    public void beforePlayTrack(int trackId) {
        int totalTracks = blankDisc.getTracks().size();
        if (trackId < 0) {
            System.out.println("输入的序号不合法 ... ");
        } else {
            if (trackId > totalTracks) {
                System.out.println("输入的序号不合法 ... ");
            } else {
                System.out.println("正在播放曲目:《"+blankDisc.getTracks().get(trackId -1 )+"》");
            }
        }
    }
}

As with the previously created section, this section use the @Pointcutannotation clearly defined cut-off point, and using @AfterReturninga method declared to return a notification. But here in different places with the cut-off point also declares the parameters to be supplied to the method of notification. The following figures were cut decomposition form:

Expression at tangent point args(trackId)qualifier is passed to indicate that playTrackById()the method of intthe type of parameters will be passed to the notification, the name of the parameter trackIdis also matched with the cut-point method signature parameters. The parameters are passed to the notification method, this method is notified by @AfterReturningthe tangent point and name annotation playTrackById(trackId)definition. Parameter name cut-off point in the definition of the parameters and cut-point method is the same, this completes the cut-off point from Pirates of the notification method name parameter transfer.

Listing: Configuring BlankDisc and BlankDiscAspectJ class in the applicationContext.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:context="http://www.springframework.org/schema/context"
    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.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd">

    <context:annotation-config />
    <!-- 启用@AspectJ注解驱动的切面 -->
    <aop:aspectj-autoproxy />
    
    <bean id="blankDiscAspectJ" class="com.aop.config.BlankDiscAspectJ"></bean>
    <bean id="blankDisc" class="com.aop.config.BlankDisc">
        <property name="discTitle" value="张学友怀旧金曲"/>
        <property name="artist" value="张学友"/>
        <property name="tracks">
            <list>
                <value>爱你痛到不知痛</value>
                <value>如果这都不算爱</value>
                <value>寂寞的男人</value>
                <value>结束不是我要的结果</value>
                <value>你说的</value>
            </list>
        </property>
    </bean>
</beans>

Listing: Test BlankDiscAspectJ section

package com.aop.config;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestBlankDisc {
    
    @Resource(name="blankDisc")
    private BlankDisc blankDisc;
    
    @Test
    public void testDemo01() {
        blankDisc.playTrackById(5);
        // 运行结果:
        // 请播放曲目:5
        // 正在播放曲目:《你说的》
    }
}

Guess you like

Origin www.cnblogs.com/martin0319/p/11585316.html