To create a notification using the Spring AOP

Write in the forefront

  • There are six types of 1.SpringAOP notice, as long as we customize a class that implements the corresponding interface, they are all org.springframework.aopin the package.
  • 2.AOP connection point may be method calls, method calls itself, class initialization, when the object is instantiated, but the SpringAOP all method calls, simpler, and most useful
Notification name interface
Before advice org.springframework.aop.MethodBeforeAdvice
Rear return notice org.springframework.aop.AfterReturningAdvice
After returning advice org.springframework.aop.AfterAdvice
Around advice org.springframework.aop.MethodInterceptor
Abnormal notice org.springframework.aop.ThrowsAdvice
Introduction advice org.springframework.aop.IntroductionInterceptor

Write a public class for the target object

public class Person {
    private String name;
    public boolean saySomething(String something){
        System.out.println("Pereson类中说了一句:"+something);
return true;//默认返回true
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

First, create a pre-notification (that is, before the target method call execution)

  • Before advice can modify the parameters passed to the method, and the method can prevent the execution by throwing an exception, to authenticate user logins can be achieved by pre-notification, SpringSecurity did just that

    1. Examples: a message before performing the method comprises a method name is written to the console, and the next incoming parameter modification. (Article written content is relatively small, most have comments in the code, you can download the code view)


/**
 * 前置通知类
 */
public class BeforeAdvice implements MethodBeforeAdvice {


    @Override
    public void before(Method method, Object[] objects, @Nullable Object o) throws Throwable {
          //第一个参数是目标方法对象,第二个是参数,第三个是做为调用目标的object(这是personr实例)
        //打印方法名
        System.out.println("要执行的方法是:"+method.getName());
        //修改参数为lyn4ever
        objects[0]="lyn4ever";//我们修改成为了lyn4ever,所以打印出来的就是lyn4ever,而不是zhangsan
    }


    public static void main(String[] args) {
        Person person = new Person();

        ProxyFactory pf  =new ProxyFactory();
        pf.addAdvice(new BeforeAdvice());
        pf.setTarget(person);

        Person proxy = (Person) pf.getProxy();

        //我这里传的参数是zhangsan,理论上它应该打印出来zhangsan
        proxy.saySomething("zhangsan");

    }

}

title

Nothing wrong, I had entered a zhangsan, it will change the parameters aop in lyn4ever, so perfect replaced.

Second, post-return notification

Is the connection point (method call) execution returns, which is obviously not as modify parameters like top, can not modify the return value. But can throw an exception can be sent to the stack, you can also call other methods.


/**
 * 后置返回通知
 */
public class AfterReturnAdvice implements AfterReturningAdvice {

    @Override
    public void afterReturning(@Nullable Object o, Method method, Object[] objects, @Nullable Object o1) throws Throwable {
        /*
        参数和前置通知是一样的
        这个是在返回之后调用,因此,person中的saySomething会先打印,我们在这里修改的参数不起作任何作用
         */

        System.out.println("调用的方法是:"+method.getName()+"这句是在saySomething之后");//这句是在saySomething之后
        objects[0]="lyn4ever";//这句可以修参数,但是之前的方法已经执行过了,所以不起任何作用

        System.out.println("我们修改了参数为:"+objects[0]+"但是没有任何用");//这时候这个参数并不会传到person.saysomething(),因为已经调用过了

    }


    public static void main(String[] args) {
        Person person = new Person();

        ProxyFactory pf = new ProxyFactory();
        pf.addAdvice(new AfterReturnAdvice());//注意修改这个为当前类中的通知类
        pf.setTarget(person);

        Person proxy = (Person) pf.getProxy();
        proxy.saySomething("zhangsan");
    }
}

title

Third, around advice

This man is best understood, that is, the code can be executed before or after the method call. Looks like a collection of pre- and post-post, but it can be modified method's return value as the return value of invoke method of its implementation is Object, so we can modify, and return the pre-notification is void, so no law changes. Even so we can not call the connection point method in the target object, we completely revised all the code for this method.

public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        return null;
    }
}

Although this invoke () method and does not provide those parameters as before, but this example can be a invocation
title
title
code sample


/**
 * 环绕通知
 */
public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        
        //在这个invoation中有一切我们想要的方法相关
        System.out.println("类名是:"+invocation.getThis().getClass().getName());
        System.out.println("目标方法是:"+invocation.getMethod().getName());

        Object[] arguments = invocation.getArguments();//这个就是参数
        System.out.println("第一个参数 是:"+arguments[0]);

        //我们修改第一个参数为lyn4ever
        arguments[0]="lyn4ever";


        invocation.proceed();//执行目标方法


        System.out.println("这个是在之后执行的");

        return false;//修改返回值
    }


    public static void main(String[] args) {
        Person person = new Person();

        ProxyFactory pf = new ProxyFactory();
        pf.addAdvice(new MyMethodInterceptor());//注意修改这个为当前类中的通知类
        pf.setTarget(person);

        Person proxy = (Person) pf.getProxy();
        boolean flag = proxy.saySomething("zhangsan");
        System.out.println(flag);//方法本来是要返回true的
    }
}

We can see, we modified the method returns the value of the target.

This article has been submitted to github demo

Guess you like

Origin www.cnblogs.com/Lyn4ever/p/11939250.html