SpringAOP knowledge points Daquan introduces the pointcut expression in detail

Knowledge point induction

1. Introduction and use of AOP entry point expressions

2. Examples to introduce the execution order of notifications

3. Round-based notification execution

4. Spring aop based on xml configuration

4. Which is better based on annotation and xml?

AOP entry point expression

Spring aop supports the realization of AspectJ cut-off identifiers, which are used to cut-off expressions. The most used are 1, 2, 4.

1. Execution is used to match method connection points, the most used pointcut identifier, can be matched to the method level, fine-grained. Based on method.

    @Before(“execution(* cn.allen.service.impl.*.*(..))”)

2. @annotation matches which methods have this annotation on them. Based on annotations.

    @Before(“@annotation(jdk.nashorn.internal.runtime.logging.Logger)”)

3. @within can only match up to the class level, and there is a certain annotation on the companion class.

4. This is used to match the class that implements an interface. Based on the interface.

5. args are matched by parameters.

The expression merges && || !, corresponding to AND or NOT

@Before(“execution(* cn.allen.service.impl.*.*(..)) && @annotation(jdk.nashorn.internal.runtime.logging.Logger)")

Execution order of Spring AOP notifications

Execution sequence: pre-position -> post-position -> post-abnormal -> post-return

正常: @Before -> Method -> @After ->  @AfterReturning

异常:@Before -> Method -> @After -> @AfterThrowing

Example descriptions of pre-notification, post-notification, post-return notification, and post-abnormal notification.

Add a knowledge point, JoinPoint is the link point we mentioned earlier, in which you can get some specific information inside the method, such as method name, method parameters, specific examples are as follows

The pre-notification @Before will be executed before the called method.

Post notification @After, executed after the called method

The post-return notification @AfterReturning is executed before the called method is about to complete and the structure is returned.

The post-exception pass @AfterThrowing, which will be executed when the called method sends a real exception.

@Component
@Aspect
public class LogAspect {
    @Before("execution(* com.allen.trainning.spring.aop.dao.impl.*.*(..))")
    public void before(JoinPoint point){
        System.out.println("@Before --- "+ point.getArgs()[0] + " is the name for a candidate girl!");
    }

    @After("execution(* com.allen.trainning.spring.aop.dao.impl.*.*(..))")
    public void after(JoinPoint point){
        System.out.println("@Before --- "+ point.getSignature().getName() + " was been called just now!");
    }

    @AfterReturning(value = "execution(* com.allen.trainning.spring.aop.dao.impl.*.*(..))", returning = "returnVal")
    public void afterReturn( Object returnVal){
        XiaoJieJie xiaojiejie = (XiaoJieJie)returnVal;
        System.out.println("@AfterReturning --- "+ xiaojiejie.getName() + " have been returned !");
    }

    @AfterThrowing(value = "execution(* com.allen.trainning.spring.aop.dao.impl.*.*(..))", throwing = "errorInfo")
    public void afterException(Exception errorInfo){
        StringWriter sw = new StringWriter();
        errorInfo.printStackTrace(new PrintWriter(sw,true));
        System.out.println("@AfterThrowing --- unexpected result happens, please check !!!" + sw.getBuffer().toString() );
    }
}

There are 2 cut methods, getByage and getByName:

@Repository
public  class GetXiaoJieJieDaoImpl implements GetXiaoJieJieDao {
    public  XiaoJieJie getByAge(Integer age){
        System.out.println("--- method getByAge is been calling ---!");
        if (age==null){
            throw new RuntimeException("age is null ,please check");
        }
        return new XiaoJieJie("Lucy",age);
    }
    public  XiaoJieJie getByName(String name){
        System.out.println("--- method getByName is been calling ---!");
        return new XiaoJieJie(name,18);
    }
}

test:

public class TestAop {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext xml = new ClassPathXmlApplicationContext("spring.xml");
        GetXiaoJieJieDao findXiaojiejie = xml.getBean(GetXiaoJieJieDao.class);
        XiaoJieJie girl = findXiaojiejie.getByName("lulu");
        girl.play();
        findXiaojiejie.getByAge(null);
    }
}

Results of the:

@Before --- lulu is the name for a candidate girl!
--- method getByName is been calling ---!
@Before --- getByName was been called just now!
@AfterReturning --- lulu have been returned !
my Master, I am lulu ,18 years old, will you play with me
@Before --- null is the name for a candidate girl!
--- method getByAge is been calling ---!
@Before --- getByAge was been called just now!
@AfterThrowing --- unexpected result happens, please check !!!java.lang.RuntimeException: age is null ,please check
	at com.allen.trainning.spring.aop.dao.impl.GetXiaoJieJieDaoImpl.getByAge(GetXiaoJieJieDaoImpl.java:13)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)

Each of the above notification methods has written its own pointcut expression, and they are all the same, which looks very inelegant. Pointcut variables, this concept can help us solve this problem. At this time, we use the pointcut annotation @PointCut, as follows

    @Pointcut("execution(* com.allen.trainning.spring.aop.dao.impl.*.*(..))")
    public void pointCut(){
    }

 Therefore, the pointcut expressions on the above notifications can be replaced with pointCut().

    @Before("pointCut()")
    @After("pointCut()")
    @AfterReturning(value = "pointCut()", returning = "returnVal")
    @AfterThrowing(value = "pointCut()", throwing = "errorInfo")

Use of Surround Notification @Around

The surrounding notification is simply a notification to replace the above four notifications, the specific implementation is as follows:

@Component
@Aspect
public class LogAspectPointCut {
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinpoint) {
        String methodName = joinpoint.getSignature().getName(); //获取方法名字
        String paraValue = (String)joinpoint.getArgs()[0];//获取方法参数
        Object object = null;
        try {
            System.out.println("前置通知" + methodName+ paraValue);
            object = joinpoint.proceed();
            System.out.println("前置通知");
        } catch (Throwable throwable) {
            System.out.println("异常通知");
        } finally {
            System.out.println("返回通知");
        }
        return object;
    }
}

Results of the:

前置通知 方法名:getByName 参数:lulu
--- method getByName is been calling ---!
后置通知
返回通知
my Master, I am lulu ,18 years old, will you play with me
前置通知 方法名:getByAge 参数:null
--- method getByAge is been calling ---!
异常通知
返回通知

Process finished with exit code 0

Configure AOP based on XML

You cannot use && in xml, you need to escape &&

The specific configuration is as follows:

The first step is to remove the configuration of the enable aop annotation

<aop:aspectj-autoproxy/>

The second step is to configure the aopconfig

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

<context:component-scan base-package="com.allen.trainning.spring.aop"/>
    <aop:config>
        <aop:aspect ref="logAspect">
            <aop:pointcut id="logPointcut" expression="execution(* com.allen.trainning.spring.aop.dao.impl.*.*(..))"></aop:pointcut>
            <aop:before method="before" pointcut="execution(* com.allen.trainning.spring.aop.dao.impl.*.*(..))&amp;&amp;execution(* com.allen.trainning.spring.aop.dao.impl.*.*(Integer))"></aop:before>
            <aop:after method="after" pointcut-ref="logPointcut"></aop:after>
            <aop:after-returning method="afterReturn" pointcut-ref="logPointcut" returning="returnVal"></aop:after-returning>
            <aop:after-throwing method="afterException" throwing="errorInfo" pointcut-ref="logPointcut"></aop:after-throwing>
        </aop:aspect>
    </aop:config>

    <aop:config>
        <aop:aspect ref="logAspectPointCut">
            <aop:pointcut id="logPointcut" expression="execution(* com.allen.trainning.spring.aop.dao.impl.*.*(..))"></aop:pointcut>
            <aop:around method="around" pointcut-ref="logPointcut" ></aop:around>
        </aop:aspect>
    </aop:config>
</beans>

The test result, which is the same as the commented test result, will not be posted twice.

What about annotations and xml, it was annotations at the time

As follows, annotations can merge multiple pointcut expressions defined by themselves, xml does not work

Annotations are also relatively simple and convenient to use.

Interview questions:

1. Which are the spring aop notification types?

2. What are the steps of annotation and xml implementation?

 

Guess you like

Origin blog.csdn.net/pengweismile/article/details/109849548