AspectJ Study Notes

Source: Internet
Author: User
Tags aop exception handling xmlns


After learning AspectJ for a while, the overall feeling of the programming language is simple and easy to learn, powerful, but the search on the basic content of aspectj less, so, I feel the need to sort out this part of the content, if there is inappropriate, welcome to learn together ☺

Content: AspectJ concepts, differences with AOP, @AspectJ configuration, advice configuration, Introduction configuration

(Source:testspring)



1 AspectJ Introduction

The encyclopedia explains it this way: AspectJ is a tangent-oriented framework that extends the Java language and defines the AOP syntax, so it has a dedicated compiler to generate class files that conform to the Java Byte encoding specification.

To put it simply, it is an AOP that is implemented in another way: ASPECTJ is an AOP implemented in annotated form at compile time. As for the role of the AOP strategy, it is important to learn the AOP basis separately.

2 The difference between aop/spring AOP/ASPECTJ


Now that ASPECTJ is an AOP framework strategy, and you've learned spring AOP before, then talk about the conceptual difference between the three.

AOP: An aspect-oriented programming paradigm, is a programming idea that aims to improve modularity by separating crosscutting concerns and spanning object concerns. The typical application of AOP is the transaction mechanism of spring, logging. AOP enables the isolation of parts of the business logic, which reduces the coupling between parts of the business logic, improves the reusability of the program, and improves the efficiency of development. The main functions are: Logging, performance statistics, security control, transaction processing, exception handling and so on; The main intent is to divide the code of logging, performance statistics, security control, transaction processing, exception handling, and so forth from the business logic code, by separating these behaviors, We want to be able to separate them into non-instructional methods of business logic, and then change those behaviors without affecting the code of the business logic.

AspectJ and Spring AOP are two implementations of AOP, and this is something to figure out.

AspectJ: ASPECTJ is a Java implementation of AOP, and AspectJ is a compile-time AOP implemented in annotated form.

(1) ASPECTJ is a code-generation tool, where ASPECTJ syntax is the syntax used to define code generation rules. Based on their own grammar compiler tool, the result of compiling is Javaclass file, run time Classpath need to include aspectj of a jar file (runtime Lib), support compile-time weaving aspect, so-called CTW mechanism, This can be done through an ant or Maven task.

(2) ASPECTJ has its own class loader, which supports the weaving of facets during class loading, the so-called LTW mechanism. With AspectJ LTW There are two main steps, first, to set the LTW's loom class package through the JVM's-javaagent parameter to proxy the JVM default ClassLoader; second, the LTW loom requires a A aop.xml file that specifies the slice class in the file and the target class that needs to be cut into slices.

(3) AspectJ also supports runtime weaving, and runtime weaving is a mechanism based on dynamic agents. (Default mechanism)

Spring AOP

Spring AOP is one of the AOP implementations that enables the aspect to be woven into the target code in the runtime based on a dynamic proxy approach to AOP. However, Spring AOP has limited pointcut support and cannot support AOP for both static and final methods (because such methods cannot generate proxy classes), and spring AOP supports only beans managed by the IOC container, and other ordinary Java classes cannot support AOP. Spring now incorporates AspectJ, which allows AOP to be implemented using ASPECTJ syntax in the spring system.

3 definition and implementation of ASPECTJ configuration of the 3.1@ASPECTJ

The @aspectj is configured for discovery by the bean container. Support for @aspectj can be configured using either an XML file configuration or a Java-style configuration, where @AspectJ annotation style is similar to plain Java annotations in plain Java classes,

Annotation form:

       @Configuration
       @EnableAspectJAutoProxy
       publicclass appconfig{
       }

XML Configuration Form

<aop:aspectj-autoproxy/>

Spring can use ASPECTJ to do pointcut parsing

While the runtime of AOP is still pure spring AOP, there is no dependency on aspectj compilers or weaving, but to use ASPECTJ, you must ensure that the Aspectjweaver.jar Library is included in the classpath of the application. And you must determine its version in 1.6.8 or later versions.

There are a few things to know:

(1) @Aspect facets are configured with @aspect annotations, any bean with @aspect will be automatically identified and applied by spring and can have all the features of the AOP configuration.

(2) Classes annotated with @aspect can have methods and fields, they may also include pointcut pointcut, notification advice, and introduction of introduction declarations.

(3) @Aspect annotations cannot be detected automatically through the classpath, you need to use @component annotations or configure the corresponding bean entries in the XML file.

These two implementations are:

annotation form:

@Component
@Aspect Public
class Terenceaspect {}

Configuration form:

<bean id= "Myaspect" class= "Org.xyz.NotVeryUsefulAspect" >
       <!--configureproperties of aspect of here as Normal-->
</bean>

It is important to note that the @aspect annotation of a class only identifies the class as a tangent and excludes itself from the automatic proxy, in order to avoid a dead loop (for example, a package that contains business classes and slice classes, excluding itself from an automatic proxy). Avoid yourself acting on your own situation and always looking for your own loop situation).


3.2 pointcut Annotations

(1) General Pointcut

A pointcut is provided by a common method definition, and the pointcut expression is declared with the @pointcut annotation, and the method return type of the annotation must be void.

@Component
@Aspect Public
class Terenceaspect {
    @Pointcut ("Execution (*com.terence.aop.aspectjbiz.*biz .**(..))")
    public void Pointcut () {}
   
    @Pointcut ("Within (com.terence.aop.aspectj.biz.*)") Public
    void Bizpointcut () {}
}

Annotations to the above Pointcut pointcuts: @Pointcut ("Execution (* com.terence.aop.aspectjbiz.*biz.** (..))") Indicates that any method that ends with a biz under package com.terence.aop.aspectjbiz will be executed.

The @Pointcut ("Within (com.terence.aop.aspectj.biz.*)") indicates that any class under the current Com.terence.aop.aspectj.biz package will match this method.

(2) Combination Pointcut

Sometimes, in accordance with the actual situation, to establish complex pointcut expressions, can be through &&, | | And. , or you can refer to the Pointcut expression by name.

   @Pointcut ("Execution (public* (..))")
   private void Anypublicoperation () {}
  
   @Pointcut ("Within (com.xyz.someapp.trading.)")
   private void Intrading () {}
  
   @Pointcut ("anypublicoperation&& intrading ()")
   private void Tradingoperation () {}

A combined expression of the above tradingoperation () that represents the simultaneous execution of @pointcut ("Execution (public * (..))") and @pointcut ("Within (com.xyz.someapp.trading.)").

Although it is necessary to create a complex pointcut expression based on the scenario, it is not recommended to use overly complex expressions, as clear and simple as possible, because the use of the responsible combination expression, when any pointcut expression modification, can easily cause a number of related issues.

(3) How to define a good pointcut

ASPECTJ itself is a compile-time AOP, the cost of checking code and matching connection points to pointcuts is expensive, so when defining pointcuts, pointcut expressions are as clear and readable as possible, so how to define a good entry point. A good entry point should include the following:

I. Select a specific type of connection point: execution, get, set, call handler

II. Determine the connection point range, e.g. within, Withincode

III. Match contextual information, such as: This,target, @annotation

Iv. pointcut expression matching type reference the following table:


3.3 Advice Annotations

1 before Advice:@Before

2.After Returning advice:@AfterReturning, the actual value returned in the notification body can be obtained;
3.After Throwing advice:@AfterThrowing
4.After (finally) advice:
The final notification must be prepared to handle both normal and abnormal return situations, which are typically used to release resources.
@Around
    Surround notification uses @around annotations to declare that the first parameter of the notification method must be a proceedingjoinpoint type, and calling Proceedingjoinpoint's proceed () method inside the notification causes the real method to be executed. Passes in a object[] object, and the values in the array are passed as a parameter to the method.
Examples of the above 5 types of notifications:
First, XML file configuration, add Automatic scan and automatic proxy two configuration

<?xml version= "1.0" encoding= "UTF-8"?> <beans
xmlns= "Http://www.springframework.org/schema/beans"
    xmlns:context= "Http://www.springframework.org/schema/context"
    xmlns:xsi= "http://www.w3.org/2001/ Xmlschema-instance "
    xmlns:aop=" HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP "
    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 " > 
        <context:component-scan base-package= "Com.terence.aop.aspectj"/>
        <aop:aspectj-autoproxy ></aop:aspectj-autoproxy>
 </beans>

Second, the business class.

packagecom.terence.aop.aspectj.biz;
Importorg.springframework.stereotype.Service;
 /* Business Class
 *
/@Service public
class Terencebiz {
   
    @TerenceMethod ("Terencebiz Save with Terencemethod ") Public
    Stringsave (String Arg)
    {
        System.out.println (" Terencebiz Save: "+arg);
        Throw Newruntimeexception ("Save failed!");
        Return "Save success!";
    }
}

Third, the Slice class

PACKAGECOM.TERENCE.AOP.ASPECTJ;
Importorg.aspectj.lang.ProceedingJoinPoint;
Importorg.aspectj.lang.annotation.After;
importorg.aspectj.lang.annotation.AfterReturning;
importorg.aspectj.lang.annotation.AfterThrowing;
Importorg.aspectj.lang.annotation.Around;
Importorg.aspectj.lang.annotation.Aspect;
Importorg.aspectj.lang.annotation.Before;
Importorg.aspectj.lang.annotation.Pointcut;
Importorg.springframework.stereotype.Component;
Importcom.terence.aop.aspectj.biz.TerenceMethod; /* Slice class */@Component @Aspect public class Terenceaspect {@Pointcut ("Execution (*com.terence.aop.aspectj.biz.*biz.*
    *(..))") public void Pointcut () {} @Pointcut ("Within (com.terence.aop.aspectj.biz.*)") public void Bizpointcut () {}//
    @Before ("Executuion (*com.terence.aop.aspectj.biz.*biz.* (..))")   @Before ("Pointcut ()") public void before () {System.out.println ("before"); } @AfterReturning (pointcut= "bizpointcut ()", returning= "returnvalue") public void afterreturning(Object returnvalue)  {System.out.println ("afterreturning:" +returnvalue); } @AfterThrowing (pointcut= "pointcut ()", throwing= "E") public void afterthrowing (RuntimeException e) {Sys
        Tem.out.println ("afterthrowing:" +e.getmessage ());
    System.out.println ("afterthrowing:" +e);    } @After ("Pointcut ()") public void After () {System.out.println ("after"); } @Around ("Pointcut ()") Public Object Around (Proceedingjoinpoint pjp) throws Throwable {System.out.
        println ("Around 1");
        Objectobj=pjp.proceed ();
        System.out.println ("Around 2");
    return obj; } @Before ("Pointcut () &&args (ARG)") public void Beforewithparam (String arg) {System.out.prin    Tln ("Before Param:" +arg); } @Before ("Pointcut () && @annotation (Terencemethod)") public void Beforewithannotation (Terencemethodterenc Emethod) {System.out.println ("Beforewithannotation:" +terencemethod.value ());}}  

Notice advice for Slice class:

The forward notification uses @before ("Pointcut ()"), which means that the cut-in expression of the method Pointcut () is inherited: Executuion (* com.terence.aop.aspectj.biz.*biz.* (..)).

The return notification uses @afterreturning (pointcut= "bizpointcut ()", returning= "ReturnValue"), which represents a cut-in expression that inherits the Pointcut () method. and accepts the return parameter returnvalue of the business class execution method.

Exception-Throwing Notification: @AfterThrowing (pointcut= "pointcut ()", throwing= "E") and return notification

Post notification using @after ("Pointcut ()")

Surround notification using @around ("Pointcut ()")

The final @before ("Pointcut () && @annotation (Terencemethod)") is the form of a custom annotation for the advice parameters described below, with the custom annotations being:

Package com.terence.aop.aspectj.biz;
Import Java.lang.annotation.ElementType;
Import java.lang.annotation.Retention;
Import Java.lang.annotation.RetentionPolicy;
Import Java.lang.annotation.Target;
/
 * * Define Annotations Terencemethod *
/@Retention (retentionpolicy.runtime)
@Target (Elementtype.method)
Public @interfaceTerenceMethod {
    String value ();
}

With the declaration of @before ("Pointcut () && @annotation (Terencemethod)"), first integrate the cut-in expression of the Pointcut () method, and then use the @annotation ( Terencemethod) introduces a custom annotation that is combined with an expression previously inherited.

Four, the test class.

Package COM.TERENCE.TEST.AOP;
Import Org.junit.Test;
Import Org.junit.runner.RunWith;
Import Org.junit.runners.BlockJUnit4ClassRunner;
Import Com.terence.aop.aspectj.biz.TerenceBiz;
Import Com.terence.test.base.UnitTestBase;
@RunWith (blockjunit4classrunner.class) Public
class Testaspectj extends Unittestbase {
    publictestaspectj ()
    {
        super ("Classpath:spring-aop-aspectj.xml");
    }
   
    @Test public
    voidtest ()
    {
        Terencebizbiz=getbean ("terencebiz");
        Biz.save ("Thisis test");
    }
}

Five, the results of the implementation

Info: JSR-330 ' javax.inject.Inject ' annotation found and supported forautowiring

Around 1

Before

Beforewithannotation:terencebizsave with Terencemethod

Beforeparam:this is test

Terencebizsave:this is test

Around 2

After

afterreturning:savesuccess!

February 19, 2017 2:18:02 pm Org.springframework.context.support.AbstractApplicationContextdoClose

Info: closingorg.springframework.context.support.classpathxmlapplicationcontext@175390b7:startup Date [Sun Feb 19 14:18:01 CST 2017]; Root of context Hierarchy


6. Advice Extension

Method 1: General form


Method 2: Detach form


Method 3: Customize annotations


Parameters and generics of advice

Spring AOP can handle the declaration of generic classes and the parameters of using methods:

Public interface sample<t>
{
    void Samplegenericmethod (T param);
    void Samplegenericcollectionmethod (collection<t> param);
}
@Before ("Execution (*. Sample+.samplegenericmethod (*)) && args (param) ") Public
void Beforesamplemethod (Mytypeparam)
{
    //advice implementation;
}
@Before ("Execution (*. Sample+.samplegenericcollectionmethod (*)) && args (param) ") Public
void Beforesamplemethod (Collection <mytype>param)
{
    //advice implementation;
}

Advice parameter name

Notification and pointcut annotations have an additional argnames attribute that can be used to specify the parameter name of the annotated method.

@Before (value= "Com.terence.lib.Pointcuts.anyPublicMehtod () &&target (beans) && @annotation ( auditable) ", argnames=" bean,auditable ") public
    Void Audit (Object bean,auditableauditable)
    {
        Auditable Code=auditable.value ();
        //.. Use code and  bean
    }

If the first parameter is Jointpoitn,proceedingjoinpoint,joinpoint.staticpart, then it can be ignored.

@Before (value= "Com.terence.lib.Pointcuts.anyPublicMehtod () &&target (beans) && @annotation ( auditable) ", argnames=" bean,auditable ") public
    Void Audit (Joinpoint jp,objectbean,auditable auditable)
    {
        Auditable Code=auditable.value ();
        //.. Use code, bean and JP
    }

3.4 Introductions

Allows a facet to declare a notification object to implement the specified interface, and provides an interface implementation class to represent these objects, annotated with the introduction using @declareparents, which defines the matching type to have a new parent.

For example: Given an interface useagetracked, and the interface has a defaultusagetracked implementation, the next section declares that all the service interface implementations implement the Useagetracked interface, The usage is the same as the configuration-based AOP, except that it is only declared here with annotations.

@Aspect public
class Terenceusagetracking {
    @DeclareParents (value= "com.terence.aop.aspectj.*+", Defaultimpl=defaultusagetracked.class) public
    static usagetracked mixin;
    @Before ("Com.terence.aop.aspectj.biz.businessService () &&this (usagetracked)") Public
    void Recordusage (usagetrackedusagetracked)
    {
        usagetracked.incrementusecount ();
    }
}

Another point: slice instantiation model

The facet instantiation model is a high-level topic, and the "Perthis" facet is implemented by making @aspect annotations perthis clauses

Each separate service object is executed with a slice instance created

Each method of the service object creates a slice instance at the first execution, and the tangent plane fails at the same time as the service object fails.

@Aspect ("Perthis (Com.terence.aop.SystemArchitecture.businessService ())") Public
class Myaspect
{
    private int somestate; 
    @Before (Com.terence.aop.SystemArchitecture.businessService ()) Public
    void Recordingserviceuseage ()
    {
        //..
    }
}


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.