AOP: Aspect Oriented Programing

Definition: a program that dynamically inserts a piece of code into a specified location of a specified method for execution during program execution.

SpringAOP: aspect oriented programming; The bottom layer is dynamic proxy;
Spring provides AOP capabilities to simplify dynamic proxies;
Use SpringAOP to complete the logging dynamic entry function;
 

Steps to use AOP features:

1) Guide package;
1. Ioc package must guide:
Commons logging -- 1.1.3.jar
spring- beans - 4.0.0.RELEASE.jar
spring- the context - 4.0.0.RELEASE.jar
spring- the core - 4.0.0.RELEASE.jar
springExpression - 4.0.0. RELEASE. The jarCopy the code

2. AOP feature pack;

Spring aop -- 4.0.0.RELEASE.jar
spring- aspects - 4.0.0. RELEASE. Jar enhanced version of the aspect oriented function: com.springsource.net.sf.cglib- 2.2.0.jar
com.springsource.org.aopalliance- 1.0.0.jar
com.springsource.org.aspectj.weaver- 1.6.8. The jarCopy the code

2) Write configuration;
<? The 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"
    xsi:schemaLocation= "http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd 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-4.0.xsd">
    <context:component-scan base-package="com.soyoungboy"></context:component-scan>
    <aop:aspectj-autoproxy/>
</beans>Copy the code

 

3), implement AOP :(log code, when the business logic runs into the specified location)
1. Configure when and where each method runs in the section class
Add both the aspect classes and the business logic components to the container
Tell The SpringIOC container which class is the Aspect class @aspect
4. Enable annotation based AOP functionality;
Code examples to achieve through Spring Aop logging code cut:
Calculator interface class:
public interface Calculator {
    
    public int add(int i,int j);
    public int sub(int i,int j);
    public int mul(int i,int j);
    public int div(int i,intj); }Copy the code

Implementation class:

package com.soyoungboy.inter;

import org.springframework.stereotype.Service;

/ * ** Business logic *@authorsoyoungboy ** /
@Service
public class MathCalculator implements Calculator {

    public int add(int i, int j) {
        int result = i +j; System.out.println("====== inside of addition");
        returnresult; }public int sub(int i, int j) {
        int result = i - j;
        returnresult; }public int mul(int i, int j) {
        int result = i * j;
        returnresult; }public int div(int i, int j) {
        int result = i / j;
        returnresult; }}Copy the code

Cut class:

package com.soyoungboy.util;

import org.aspectj.lang.annotation.After;
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.springframework.stereotype.Component;

/ * ** Section class *@authorsoyoungboy ** /
@Component
@Aspect
public class LogUtils {

    / * ** try{* @before: * method.invoke(.....) ; * @afterreturning *} Catch (e){* @afterthrowing *}finally{* @after *} * * * meaning to run Before the target method runs: AfterReturning: The method executes normally and returns a return notification. * @AfterThrowing: the method calls an exception notification After an exception occurs. * @around: The most powerful advice (which is the dynamic proxy) uses pointcut expressions around advice to specify which methods to intercept; * Full description of the access control return value type method (parameter list)* /

    //The log began to
    @Before(value="execution(public int com.soyoungboy.inter.MathCalculator.*(int, int))")
    public static voidlogStart(){ System.out.println("XXX method start, parameter list [XXX]"); }//The log method returns normally
    @AfterReturning(value="execution(public int com.soyoungboy.inter.MathCalculator.*(int, int))")
    public static voidlogReturn() { System.out.println("XXX method returns normal, return value: XXX"); }//Log Exception
    @AfterThrowing(value="execution(public int com.soyoungboy.inter.MathCalculator.*(int, int))")
    public static voidlogException() { System.out.println("XXX method exception, exception message: XXX"); }//Methods the end
    @After(value="execution(public int com.soyoungboy.inter.MathCalculator.*(int, int))")
    public static voidlogEnd() { System.out.println("End of XXX method"); }}Copy the code

Junit test code:

package com.soyoungboy.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.soyoungboy.inter.Calculator;
import com.soyoungboy.inter.MathCalculator;

public classAOPTest { ApplicationContext ioc= new ClassPathXmlApplicationContext("beans.xml");
    
    
    
    / * ** if there is no interface, our cglib will act as the parent template based on the current class. Create a built-in proxy object;* /
    @Test
    public voidtest02(){ MathCalculator bean= (MathCalculator) ioc.getBean("mathCalculator");
System.out.println(bean.getClass()); bean.add(2, 3); }/ * ** Always use the interface type if you have one, because the component you get is a proxy object. * Implements the same interface as the proxied object* /
    @Test
    public void test01(){
        //MathCalculator calculator = new MathCalculator();
        //calculator.add(1, 2);
        //1. Write the interface type//Calculator calculator = ioc.getBean(Calculator.class);
        Calculator calculator = (Calculator) ioc.getBean("mathCalculator"); calculator.add(1, 3);
        
        
        //The container holds the proxy object for this component; If it is a component that cuts dynamically.//com.sun.proxy.$Proxy12
System.out.println(calculator.getClass()); Class<? >[] classes =calculator.getClass().getInterfaces(); System.out.println(classes[0]); }}Copy the code

The test2 method can be executed if MathCalculator is not implemented:

The result is:

classCom. Soyoungboy. Intel. MathCalculator EnhancerByCGLIB? 97 f6d938 XXX method, parameter list "XXX"= = = = = =The XXX method returns normally with the value: XXXCopy the code

Test01 executes in the case of MathCalculator implementation Calculator:

The result is:

XXX method start, parameter list [XXX]= = = = = =The XXX method returns normally with the value: XXXclass com.sun.proxy.$Proxy13
interface com.soyoungboy.inter.CalculatorCopy the code

The comments section talks about getting method information, so let’s talk about aop in detail:

The details of aop

The method name of the method at the current join point, the parameter values currently passed in, and so on. This information is encapsulated in the JoinPoint instance object.

 

notice

An overview of the

The operation to be performed at a specific join point.

A section can contain one or more notifications.

The value of the annotation used for advice is often a pointcut expression.

Pre notice

Pre-notification: Notifications executed Before method execution use the @before annotation

The rear notice

Post-notification: Post-notification is executed After the join point has completed, using the @After annotation when the join point returns a result or throws an exception


Return to inform

Return notification: Post-notification is executed whether the join point returns normally or throws an exception. If you want to log only when the join point returns, use return notifications instead of post notifications. Access the return value of a join point in a return notification using the @AfterRETURNING annotation. In a return notification, you can access the return value of a join point by adding a RETURNING attribute to the @AfterRETURNING annotation. The value of this property is the name of the parameter used to pass in the return value. You must add a parameter of the same name to the signature of the notification method. Spring AOP passes the return value through this parameter at run time. The original pointcut expression needs to appear in the Pointcut property

 

Abnormal notice

Exception notification: Exception notification is performed only when an exception is thrown by a join point. Add the Throwing attribute to the @AfterThrowing annotation and also access exceptions thrown by a join point. Throwable is the top-level parent of all error and exception classes, so any errors and exceptions can be caught in the exception notification method. If you are only interested in a particular exception type, you can declare the parameters as the parameter types of other exceptions. Notifications are then executed only when exceptions of this type and its subclasses are thrown

Surrounding the notification

Wraparound advice is the most powerful of all notification types, giving you complete control over join points and even whether they are executed. For wrap advice, the join point parameter type must be ProceedingJoinPoint. It is a subinterface of JoinPoint and allows you to control when and if join points are executed. The ProceedingJoinPoint’s proceed() method needs to be explicitly called in the surround notification to execute the propped method. Forgetting to do so would result in the notification being executed, but the target method was not. Note: the method surrounding the notification needs to return the result of the target method’s execution, which is a call to joinPoint.proceed(); Otherwise a null pointer exception will occur.

 

Reusing pointcut definitions

When writing AspectJ facets, you can write pointcut expressions directly in notification annotations. But the same pointcut expression can be repeated in multiple notifications. In AspectJ facets, you can declare a Pointcut as a simple method with the @Pointcut annotation. The method body of a pointcut is usually empty because it makes no sense to mix the pointcut definition with the application logic. The access controller for a pointcut method also controls the visibility of that pointcut. If pointcuts are to be used across multiple facets, it is best to centralize them in a common class. In this case, they must be declared public. When introducing this pointcut, you must also include the class name. If the class is not in the same package as the aspect, you must also include the package name. Other advice can introduce this pointcut through the method name

Specifies the priority of the cut

When more than one aspect is applied to the same join point, their priority is uncertain unless explicitly specified. The priority of the aspect can be specified by implementing the Ordered interface or using the @Order annotation. Implementing Ordered interface, the smaller the return value of getOrder(), the higher the priority. If you use the @order annotation, the ordinal number appears in the annotation

No more nonsense, on the code:

package com.soyoungboy.util;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/ * *
 * @authorSoyoungboy * 1, in the section class, configure when and where each method is run * order specifies the priority* /
@Order(2)
@Component
@Aspect
public class LogUtils {
    
    
    / * ** Extract reusable pointcut expressions * Define a reusable pointcut expression that future expressions reference directly;* /
    @Pointcut("execution(public int com.soyoungboy.inter.MathCalculator.*(..) )")
    public void myPoint(){}
    
    
    
    / * *Object result = null; try { LogUtils.logStart(method, args); // @before // Result = method.invoke(CAL, args); LogUtils.logReturn(method, result); //@AfterReturning } catch (Exception e) { LogUtils.logException(method,e); // @afterthrowing // For dynamic proxies, we generally recommend that exceptions continue to be thrown, so that the outside world can know; throw new RuntimeException(e); } finally{// Record method finally end logutils.logend (method); //@After } return result; * * * * cut logging code into business logic methods; Spring provides a few simple annotations; * Can be marked on methods, meaning that the method will run at the specified location * @before: pre-notification; Runs before the target method runs; * * @after: post-notification: run when the target method finally ends; * * @afterRETURNING: Return notification: run after the target method returns normally; * @afterthrowing: Exception notification: run * * * * @around (later) * * after an exception occurs in the target method@parammethod *@param args
     * /
    //The method starts by recording the parameters used//Pointcut expressions: Specify which methods are dynamically cut in when they are executed//Execution (Full class name of the return value type. Method name (parameter type list)
    @Before("myPoint()")
    public static void logStart(JoinPoint joinPoint){
        //1. Get the target method runtime parameter list of the method; Result = method.invoke(CAL, [args]);
        Object[] args = joinPoint.getArgs();
        //2. Obtain method signature; All the details of the current method are in
        Signature signature = joinPoint.getSignature();
        //3. Get the method name
        String name =signature.getName(); System.out.println("LogStart: method name: ["+name+"] method started; ["+ arrays.asList (args)+"]"); }/ * ** point expressions: * execution (public int com. Soyoungboy. Intel. MathCalculator. * (int, int)) * execution (access control operator returns a value type The full name of the class. Method name (parameter type list)); * * provides two types of wildcards: * * : matches any number of characters; * execution(public int com.soyoungboy.inter.*. A *(*, int)) * execution(public int com.soyoungboy.inter. * execution(public int com.soyoungboy.inter.*.*(int,*)) * Only two arguments can be matched, but the last argument is any * *.. : Matches any multiple characters and parameters. * 1),.. Execution (public int com.soyoungboy.impl.*.*(..)) ) * Represents any parameter of any method of any class (the number type is unlimited); * * execution(public int com.soyoungboy.impl.*.*(int,..) ) * can match any argument, but the first argument must be int * 2. Write at package level: match multiple paths * * * In particular: Access control (either not written, or public only) * * * Most obscure: * execution(* *(..)) The most detailed) * : * execution (public int com. Soyoungboy. Impl. MathCalculator. The add (int, int)) * * advanced application: * &&: and * eg: Cut into the position, than must satisfy the preceding expression must also satisfy the following expression. Intersection * execution (public int com. Soyoungboy. Impl. MathCalculator. Add (..) ) && execution ((int, int)) * * * div (int, int) will not cut, the add (int, int) will cut * | | : * eg: cut into the position of the expression in front of or behind it; As long as meet an arbitrary expression conditions can * execution (public int com. Soyoungboy. Impl. MathCalculator. Add (..) ) | | execution ((int, int)) * * * div (int, int) will be cut, the add (int, int) will be cut* /
    @AfterReturning(value="myPoint()",returning="data")
    public static voidlogReturn(JoinPoint joinPoint,Object data){ System.out.println("[log] Return notification ["+joinPoint.getSignature().getName()+"]" "); }/ * ** Method details, such as return value, exception, [method name], [parameter list]... How to obtain; * 1) Returning a dichotomy: Specify which returning parameter (s) is returning a value * of the specified type and will not be called * 2) throwing error notification * NullPointerException: The current notification method is only used to accept NullPointerException; If the target method has other exceptions, the notification methods will not be called. * JoinPoint JoinPoint (encapsulates details of the current JoinPoint); * AJAX: similar; * $.ajax({ * url:"xxx", * success:function(data){ * alert(data) * } * }) ** /
    @AfterThrowing(value="myPoint()",throwing="e")
    public static voidlogException(JoinPoint joinPoint,Exception e) { System.out.println(["+joinPoint.getSignature().getName()+"]); }/ * ** Post-notification * 1. Constraints on notification methods; * There is only one constraint; Parameter list Spring must know what each parameter represents; * * AOP detail 5: * The order in which notification methods are called; @Before @After @AfterReturning @AfterThrowing * try{ * @Before * method.invoke(obj,args); * @afterreturning *}catch(Exception e){* @afterthrowing *}finally{* @after *} @before == target method execution => @afterreturning ==> @afterthrowing * *@param joinPoint
     * /
    @After("myPoint()")
    public int logEnd(JoinPoint joinPoint) {
        // TODO Auto-generated method stubPrintln (" +joinPoint.getSignature().getName()+") End;);
        return 1; }/ * ** @before * @after * @afterthrowing * @Afterreturing * * @around: 4. in one Is a dynamic proxy; * parameters: * several points of concern: * 1) return the target method after execution; * return proceed = pjp.proceed(args); * 2) Throw anomalies out to facilitate external perception; * 3) Several locations around with other notifications: execution order; * The surround notification has the highest priority in its own slice, and is executed first; Surround first in first out; 【 Add 】 The method has started running; Parameter list used [[10, 1, 1]] method internal print: 11 [surround] return notification, return value: 11 [surround] post notification [Log] post notification [add] Final end; 【 log 】 return notification 【add】 return normal, return value: [11] * * * multi-section with surround order: * background: BV order1 LOG(normal + wrap) order2 * BV== front * LOG== front * LOG== front * target method * LOG== return * LOG== back * BV=== after * BV=== returns * * * around a single section environment: * LOG LOG = = = = = = around front * front * target method * LOG LOG = = = = = = around return * around the rear * LOG LOG = = = = = = rear * return business logic: * * ** /
    @Around("myPoint()")
    publicObject logAround(ProceedingJoinPoint pjp){ Object[] args=pjp.getArgs(); Object proceed= null;
        try {
            
            //Object result = method.invoke(arg0);
            //Advance the execution of the target method, pass in the parameters to be used when the target method is executed, and return the value of the target method after execution//@BeforeSystem.out.println(");
            //Release target method executes...
            proceed = pjp.proceed(args);
            //@AfterReturingSystem.out.println(" [surround] returns notification, return value: "+proceed); }catch (Throwable e) {
            //e.printStackTrace();
            //@AfterThrowing
            //Abnormal information is usually thrown out for the outside world to perceiveSystem.out.println(" [surround] exception notification "));
            throw newRuntimeException(e); }finally{
            //@AfterSystem.out.println("); }returnproceed; }}Copy the code

 

 

【J2EE】
Good writing is the best
Pay attention to my
Collect the paper

Northwest Wolf



Attention – 3



Fans – 29

+ add attention

0
0

The «The last:
Interview question 1 — How do you display time zones in a formatted date in Java?



» Next up:
Set up James mail server