SpringBoot configuration aop

Source: Wu Weifeng original article

aop spring is one of the two functional modules, very powerful, for the decoupling provides a very good solution.
Now to use springboot in to find out aop aop.

A: aop accomplished using a global request log processing

Springboot create a web project, check aop, pom follows:

<?xml version="1.0" encoding="UTF-8"?>  
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
        <modelVersion>4.0.0</modelVersion>  

        <groupId>com.example</groupId>  
        <artifactId>testaop</artifactId>  
        <version>0.0.1-SNAPSHOT</version>  
        <packaging>jar</packaging>  

        <name>testaop</name>  
        <description>Demo project for Spring Boot</description>  

        <parent>  
            <groupId>org.springframework.boot</groupId>  
            <artifactId>spring-boot-starter-parent</artifactId>  
            <version>1.5.3.RELEASE</version>  
            <relativePath/> <!-- lookup parent from repository -->  
        </parent>  

        <properties>  
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>  
            <java.version>1.8</java.version>  
        </properties>  

        <dependencies>  
            <dependency>  
                <groupId>org.springframework.boot</groupId>  
                <artifactId>spring-boot-starter-aop</artifactId>  
            </dependency>  
            <dependency>  
                <groupId>org.springframework.boot</groupId>  
                <artifactId>spring-boot-starter-web</artifactId>  
            </dependency>  

            <dependency>  
                <groupId>org.springframework.boot</groupId>  
                <artifactId>spring-boot-starter-test</artifactId>  
                <scope>test</scope>  
            </dependency>  
        </dependencies>  

        <build>  
            <plugins>  
                <plugin>  
                    <groupId>org.springframework.boot</groupId>  
                    <artifactId>spring-boot-maven-plugin</artifactId>  
                </plugin>  
            </plugins>  
        </build>  


    </project>  

Creating a controller

package com.example.controller;  

    import org.springframework.web.bind.annotation.RequestMapping;  
    import org.springframework.web.bind.annotation.RestController;  

    /** 
     * Created by wuwf on 17/4/27. 
     * 
     */  
    @RestController  
    public class FirstController {  

        @RequestMapping("/first")  
        public Object first() {  
            return "first controller";  
        }  

        @RequestMapping("/doError")  
        public Object error() {  
            return 1 / 0;  
        }  
    }  

Creating a class aspect cut

    package com.example.aop;  

    import org.aspectj.lang.JoinPoint;  
    import org.aspectj.lang.ProceedingJoinPoint;  
    import org.aspectj.lang.annotation.*;  
    import org.springframework.stereotype.Component;  
    import org.springframework.web.context.request.RequestContextHolder;  
    import org.springframework.web.context.request.ServletRequestAttributes;  

    import javax.servlet.http.HttpServletRequest;  
    import java.util.Arrays;  

    /** 
     * Created by wuwf on 17/4/27. 
     * 日志切面 
     */  
    @Aspect  
    @Component  
    public class LogAspect {  
        @Pointcut("execution(public * com.example.controller.*.*(..))")  
        public void webLog(){}  

        @Before("webLog()")  
        public void deBefore(JoinPoint joinPoint) throws Throwable {  
            // 接收到请求,记录请求内容  
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();  
            HttpServletRequest request = attributes.getRequest();  
            // 记录下请求内容  
            System.out.println("URL : " + request.getRequestURL().toString());  
            System.out.println("HTTP_METHOD : " + request.getMethod());  
            System.out.println("IP : " + request.getRemoteAddr());  
            System.out.println("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());  
            System.out.println("ARGS : " + Arrays.toString(joinPoint.getArgs()));  

        }  

        @AfterReturning(returning = "ret", pointcut = "webLog()")  
        public void doAfterReturning(Object ret) throws Throwable {  
            // 处理完请求,返回内容  
            System.out.println("方法的返回值 : " + ret);  
        }  

        //后置异常通知  
        @AfterThrowing("webLog()")  
        public void throwss(JoinPoint jp){  
            System.out.println("方法异常时执行.....");  
        }  

        //后置最终通知,final增强,不管是抛出异常或者正常退出都会执行  
        @After("webLog()")  
        public void after(JoinPoint jp){  
            System.out.println("方法最后执行.....");  
        }  

        //环绕通知,环绕增强,相当于MethodInterceptor  
        @Around("webLog()")  
        public Object arround(ProceedingJoinPoint pjp) {  
            System.out.println("方法环绕start.....");  
            try {  
                Object o =  pjp.proceed();  
                System.out.println("方法环绕proceed,结果是 :" + o);  
                return o;  
            } catch (Throwable e) {  
                e.printStackTrace();  
                return null;  
            }  
        }  
    }  

Startup Items
situation simulate normal execution, access to HTTP: // localhost: 8080 / First , look at the results of the console:

Methods surround ... .. Start
the URL of: HTTP: // localhost: 8080 / First
HTTP_METHOD: GET
IP: 0: 0: 0: 0: 0: 0: 0: 1
CLASS_METHOD: com.example.controller.FirstController.first
ARGS: []
method surround proceed, the result is: first controller
method of performing the last ... ..
return value: first controller
/ ************************************************** parting line ***** ************* /
simulation case when an exception occurs, visit HTTP: // localhost: 8080 / DoError , see the console results:
method surround ... .. Start
the URL of: HTTP: // localhost : 8080 / DoError
HTTP_METHOD: the GET
the IP: 0: 0: 0: 0: 0: 0: 0:. 1
CLASS_METHOD: com.example.controller.FirstController.error
ARGS: []
java.lang.ArithmeticException: / ZERO by
......
method of performing the last ... ..
Return value method: null
/ ************************************************** parting line ****** ************ /
simple example above, the order of execution can be seen that the aop. Knows the order, the processing section can be made in the corresponding position.

II: Method Description section

@Aspect
effect of the current class is identified as a container section for reading
@Before
identifying a pre-enhancement methods, the functional equivalent BeforeAdvice
@AfterReturning
rear reinforcement, corresponding to the AfterReturningAdvice, when performing the method exits
@AfterThrowing
exception is thrown enhanced, equivalent ThrowsAdvice
@After
Final enhanced, whether it is throwing an exception or normal exit will be executed
@Around
surround enhancement, equivalent to MethodInterceptor
/ ****************** dividing line *** *************** /
respective methods parameters:
addition @Around, where each method can be applied with or without additional parameters JoinPoint, if it is useful to add JoinPoint place, without also can, the JoinPoint contains the class name, a method name to be cut, the attribute parameters, used for reading. @Around parameter must ProceedingJoinPoint, pjp.proceed performing the method corresponding to the cut surface. @AfterReturning method where you can add returning = "XXX", XXX is the return value of the method in the controller, the return value in the present embodiment is a "first controller". @AfterThrowing method where you can add throwing = "XXX", for reading the abnormality information, as in the present embodiment can be changed to:

    //后置异常通知  
   @AfterThrowing(throwing = "ex", pointcut = "webLog()")  
   public void throwss(JoinPoint jp, Exception ex){  
      System.out.println("方法异常时执行.....");  
    }  

It is commonly used in combination before and afterReturn or Around used alone, to obtain cut before the beginning and after the end of the method.

Three: the starting point on the section PointCut

execution point cut function

execution function for executing a connection point matching method, the syntax is:
execution (Method modifier (optional) method returns the type of the abnormal pattern parameter name (optional))
parameter section Wildcards:
* matches any character, but only match an element
.. matches any character can match any number of elements, it said in class, and must be used in conjunction *
+ must follow after the class name, such as the Horseman +, represents the class itself and all classes inherit or extend the specified class
reference: HTTP : //blog.csdn.net/autfish/article/details/51184405

In addition to execution (), Spring also supports a number of other functions, to name names and a brief introduction to facilitate a more detailed inquiry needed
@annotation ()
represents a marked target class designated annotation methods
such as @annotation (org. springframework.transaction.annotation.Transactional) @Transactional showing a method of labeling
args ()
by the method of the target class parameter types specified cut-off point
, for example, args (String) String indicates one and only one type of parameter method
@args ()
through the target object type class parameters specify whether the annotation marked tangent point designated
as @args (org.springframework.stereotype.Service) label indicates one and only one parameter class @Service a method
WITHIN ()
class name designated tangent point
as with (examples.chap03.Horseman) represents all the methods Horseman
target ()
by the class name is specified, it contains all subclasses
such as target (examples.chap03.Horseman) and Elephantman extends Horseman, all methods in the two classes match
! within ()
match marked the class and all subclasses of the specified comment
The @within (org.springframework.stereotype.Service) @Service to add labels Horseman, Horseman and all the methods are matched Elephantman
@target ()
All classes given annotation marked
as @target (org.springframework.stereotype. -Service) represents all methods of all classes marked @Service
this ()
most of the time and target () the same, this difference is generated at run time after the proxy class, the type of the object is determined before the specified proxy class matches

/ ****************** dividing line ****************** /

Logical operator
expression may be composed of a plurality of cutting points by logical operation function
&&
operation, intersection of, and may be written
, for example, execution (* chop (..)) && target (Horseman) represented chop method and its subclasses Horseman
||
or operation, seek and set, or may be written
, for example, execution (* chop (..)) || args (String) represents the name of a method or as a chop has a String parameter method
!
inoperative, set negated , can also be written not
for example execution (* chop (..)) and! args (String) method is a method name can not chop but there is only one type String parameter representation

used to match a particular execution method, such as how to deal with during update, or certain types of matching, if all of the controller class, the larger cut-ranging mode, or the transaction logs are used for processing.
Several other usage is different, as the case may select.
Above the red mark of the more common. Let's look at the annotation.

Four: custom annotation

Usually used for certain features, fragmented facets, such methods require certain specific processing, annotations can be added separately in the method section.
We customize a comment:

package com.example.aop;  

    import java.lang.annotation.ElementType;  
    import java.lang.annotation.Retention;  
    import java.lang.annotation.RetentionPolicy;  
    import java.lang.annotation.Target;  

    /** 
     * Created by wuwf on 17/4/27. 
     */  
    @Target({ElementType.METHOD, ElementType.TYPE})  
    @Retention(RetentionPolicy.RUNTIME)  
    public @interface UserAccess {  
        String desc() default "无信息";  
    }  

Notes in desc provides a method of, for the section of the local mass participation, if you do not pass argument can not write.

Controller method in Riga

    @RequestMapping("/second")  
        @UserAccess(desc = "second")  
        public Object second() {  
            return "second controller";  
        }  

Section categories:

    @RequestMapping("/second")  
        @UserAccess(desc = "second")  
        public Object second() {  
            return "second controller";  
        }  

The main look @Around comment here, if you need to get in the controller assigned to UserAccess desc annotation in the value of such an approach is required, so have the value of the parameter UserAccess.
/ ****************** dividing line ****************** /
start the project, visit http: // localhost: 8080 / SECOND, , see the console:

Methods surround ... .. Start
the URL of: HTTP: // localhost: 8080 / SECOND,
HTTP_METHOD: GET
IP: 0: 0: 0: 0: 0: 0: 0: 1
CLASS_METHOD: com.example.controller.FirstController.second
ARGS: []
SECOND around: SECOND
SECOND before
method surround proceed, the result is: second controller
method of performing the last ... ..
return value: second controller
/ ************************************************** divided line ****************** /
notification results can be seen, two aop cut classes to work, it is the following sequence

spring aop is a concentric circle method to execute a circle, the smallest of the outermost layer order. From the outermost according AOP1, AOP2 order sequentially performed doAround method, doBefore method. The method of method is then performed, in accordance with the final AOP2, AOP1 order sequentially performed doAfter, doAfterReturn method. That multiple AOP, the first before, and certainly after after.
For the above example is that the outer layer is first of all cut to the controller, the inner layer is a custom annotations.
That a different section, the order of how it decided, in particular, deal with the same section formats, such as the case of two execution, that spring out which is randomly decide which included a.
So in most cases, we need to specify the order, the easiest way is to add @Order on the Aspect aspect class (1) Notes to, order the smaller performed first, which is located in the outermost layer. Like some global process can put order set smaller, specific to a detail on a bigger number.

Guess you like

Origin blog.csdn.net/taoism_jerry/article/details/80770329