Core 010-Spring aop 001- Description - intercept specified classes and methods, based on a custom annotations section

I. Overview

  Aspect Oriented Programming (AOP) is a supplement for object-oriented programming (OOP), and can be non-invasive introduced into the same behavior as the public does not have multiple inheritance of objects, such as logs, security, transactions, performance monitoring, and so on. SpringAOP allows the common behavior pulled out from the business logic, and which acts in a non-invasive manner woven into all the business logic in need thereof, compared to the business logic implemented OOP portrait mode, a direction which is concerned horizontal section.

  Spring2.0 from the start, the introduction of the AspectJ annotations to annotate POJO, to support the flexible definition of the point cut by cutting point functions, logical operators, wildcards, and other advanced features, in conjunction with various types of notice to form a strong connection point descriptive ability.

Second, using the example

2.1, exemplary base intercept specified classes and methods

1、pom

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
</dependency>

or

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

Core modules: Both effects are the same, the core module Spring Spring core, Spring beans, Spring context, Spring aop and AspectJ annotation provide library aspectjweaver introduction project. (SpringBoot further including automatic configuration of specific modules, etc.)

2, the normal business logic

@Service
public class MyTestService {
    Logger logger = LoggerFactory.getLogger(MyTestService.class);
    public String doSomething1(){
        logger.info("invoking doSomething1......");
        return "doSomething1";
    }

    public String doSomething2(){
        logger.info("invoking doSomething2......");
        return "doSomething2";
    }
}
View Code

3, the definition section

@Aspect
@Component
public class MyIntercepter {
    private static final Logger logger = LoggerFactory.getLogger(MyIntercepter.class);
    @Pointcut("execution(public * com.github.bjlhx15.springaop.service.MyTestService.doSomething1*(..))")
    public void doSomethingPointcut(){};

    @Before("doSomethingPointcut()")
    public void auth(JoinPoint pjp) throws Throwable{
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method Method, = signature.getMethod (); // Get the intercepted method 
        String methodName = method.getName (); // Get the name of the method to be intercepted 
        logger.info ( "certification authority: calling method: {}" , methodName );
    };

    @AfterReturning(value = "doSomethingPointcut()", returning = "returnVal")
    public void logNormal(JoinPoint pjp, Object returnVal) throws Throwable{
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method Method, = signature.getMethod (); // Get the intercepted method 
        String methodName = method.getName (); // Get the name of the method to be intercepted 
        logger.info ( "normal return diary: invoke method is: {}; returns a value of: {} " , methodName, returnVal);
    };

    @AfterThrowing(value = "doSomethingPointcut()", throwing = "e")
    public void logThrowing(JoinPoint pjp, Throwable e) throws Throwable{
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method Method, = signature.getMethod (); // Get the intercepted method 
        String methodName = method.getName (); // Get the name of the method to be intercepted 
        logger.info ( "throws an exception log record: Call method: {} ; exception information: {} " , methodName, e.getMessage ());
    };

    @After(value = "doSomethingPointcut()")
    public void afterall(JoinPoint pjp) throws Throwable{
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method Method, = signature.getMethod (); // Get the intercepted method 
        String methodName = method.getName (); // Get the name of the method to be intercepted 
        logger.info ( "method call is completed: the calling method is: {}" , methodName);
    }

    @Around("doSomethingPointcut()")
    public Object timer(ProceedingJoinPoint pjp) throws Throwable{
        long beginTime = System.currentTimeMillis();
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method Method, = signature.getMethod (); // Get the intercepted method 
        String methodName = method.getName (); // Get the name of the method to be intercepted 
        logger.info ( "Timing section: requests to start, method: {}" , methodName);

        Result Object = null ;
         the try {
             // all normal circumstances, the method continues to be intercepted 
            Result = pjp.proceed ();
        } catch (Throwable e) {
            logger.info("exception: ", e);
        }
        long endTime = System.currentTimeMillis();
        logger.info ( "timing aspect: the request end, the method: {}, the execution time: {}", methodName, (endTime- beginTime));
         return Result;
    }
}
View Code

  The above defines a tangent point Pointcut, and around this point cut 5 defines different types of notification Advice, each contact point and execution logic up notifications together constitute a section Advisor, for each execution of the method time point cut, to perform certain logic.

4, call

  This will then call that is a corresponding section information, test

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ApplicationMain.class)
public class MyTestServiceTest {
    @Autowired
    MyTestService myTestService;

    @Test
    public void doSomething1() {
        myTestService.doSomething1();
    }
}

Export

cgbsinterceptor.MyIntercepter: timing aspect: Request start method: doSomething1
cgbsinterceptor.MyIntercepter: certification authority: Call method: doSomething1
c.g.b.springaop.service.MyTestService    : invoking doSomething1......
cgbsinterceptor.MyIntercepter: cgbsinterceptor.MyIntercepter: method call completes: Call method: doSomething1
cgbsinterceptor.MyIntercepter: diary normal return: call method: doSomething1; return result: doSomething1

  In a non-invasive form of method calls before and after the increase in the number of cross-section of the business logic, business logic code and do not have to care about these cross-cutting logic, only need to focus on achieving their business logic just fine.

  In the actual implementation of them, cut around method invocations we are beginning to define the execution. SpringAOP section to ensure that we define woven into the business logic code, and play a role in the implementation.

  Further the results shown in the order of execution of the plurality of facets is also not performed in the order defined by the method.

2.2, based on the custom annotation section

  Use direct execution (public * com.github.bjlhx15.springaop.service.MyTestService.doSomething1 * (..)) This section defines the actual way classpath, the class or method name tightly bound, is not conducive to expansion, subsequent You need to write using a section of people who can continue.

  We want to start like that based on a custom annotation SpringCache way various facets, SpringAOP to support this approach by cutting point function @annotation and @Within.

1, pom ibid.

2, defined Note

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestLogger {
}
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface TestTimer {
}

  Wherein TestLogger defined annotations on class; TestTimer method defined in Notes.

3. The definition is based on a custom annotation section

@Aspect
@Component
public class MyIntercepter2 {
    private static final Logger logger = LoggerFactory.getLogger(MyIntercepter2.class);

    @Pointcut("@annotation(com.github.bjlhx15.springaop.anno.TestTimer)")
    public void timerPointcut(){};

    @Pointcut("@within(com.github.bjlhx15.springaop.anno.TestLogger)")
    public void recordLogPointcut(){};

    @Before("recordLogPointcut()")
    public void log(JoinPoint pjp) throws Throwable{
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method Method, = signature.getMethod (); // Get the intercepted method 
        String methodName = method.getName (); // Get the name of the method to be intercepted 
        logger.info ( "Start diary: invoke method is: {}" , methodName);
    }

    @Around("timerPointcut()")
    public Object timer(ProceedingJoinPoint pjp) throws Throwable{
        long beginTime = System.currentTimeMillis();
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method Method, = signature.getMethod (); // Get method intercepted 
        String methodName = method.getName (); // Get the name of the method to be intercepted 

        logger.info ( "Start Request, method: {}" , methodName);

        Object result = null;

        the try {
             // all normal circumstances, the method continues to be intercepted 
            Result = pjp.proceed ();
        } catch (Throwable e) {
            logger.info("exception: ", e);
        }
        long endTime = System.currentTimeMillis();
        logger.info ( "end of the request process: {}, the execution time: {}", methodName, (endTime- beginTime));
         return Result;
    }
}

  The code represents fought like @TestLogger comments, all of which method will be called when the diary; regardless of the class, which played @TestTimer annotation methods will monitor its execution time.

  Cut point function @annotation indicates matching annotations on the tangent point function @within indicates a match based annotation on.

4, write the business logic and use the comment section

@Service
@TestLogger
public class MyTestService2 {
    Logger logger = LoggerFactory.getLogger(MyTestService2.class);
    public String sayHello(){
        logger.info("invoking method sayHello......");
        return "Hello world!";
    }

    @TestTimer
    public int count(){
        logger.info("invoking method count......");
        return 10;
    }
}
View Code

According to the comments in the service MyTestService2, meaning its expression is need to remember when MyTestService2 logs all method calls, in addition count () method is called when the need to monitor the execution time.

5, test output

 cgbsinterceptor.MyIntercepter2: the beginning of the diary: Call method: sayHello
 c.g.b.springaop.service.MyTestService2   : invoking method sayHello......
 cgbsinterceptor.MyIntercepter2: Request start method: count
 cgbsinterceptor.MyIntercepter2: the beginning of the diary: Call method: count
 c.g.b.springaop.service.MyTestService2   : invoking method count......
 cgbsinterceptor.MyIntercepter2: termination request, method: COUNT, execution time: 0

As seen above, we marked due to the different annotations, when calling the method sayHello only logical record logs cut in, but when you call the method count, the diary and logic monitors the execution time are cut into the came.

 

 

Guess you like

Origin www.cnblogs.com/bjlhx/p/12081300.html