Spring-AOP Basics

Source: Internet
Author: User

Spring-AOP Basics
Dynamic proxy

Will we encounter this situation during our daily development?

The red box shows the logs to be output. Do you find that most of the information in the logs is the same? If we want to modify a place, we need to modify all the logs, and the code looks redundant.

Next we can solve this problem through dynamic proxy.
Check the code

public interface Calculation {    public int add(int x, int y);    public int sub(int x, int y);    public int mul(int x, int y);    public int dev(int x, int y);}

Define the interface and add, subtract, multiply, and divide methods.

public class CalculationImpl implements Calculation {    @Override    public int add(int x, int y) {        int result = x + y;        return result;    }    @Override    public int sub(int x, int y) {        int result = x - y;        return result;    }    @Override    public int mul(int x, int y) {        int result = x * y;        return result;    }    @Override    public int dev(int x, int y) {        int result = x / y;        return result;    }}

The specific implementation class is as follows: no logs are embedded.

public class CalculationProxy {    private Calculation calculation = null;    CalculationProxy(Calculation calculation) {        this.calculation = calculation;    }    public Calculation getCalculationLog() {        Calculation proxy = null;        ClassLoader loader = calculation.getClass().getClassLoader();        Class[] interfaces = new Class[] { Calculation.class };        InvocationHandler h = new InvocationHandler() {            @Override            public Object invoke(Object proxy, Method method, Object[] args)                    throws Throwable {                System.out                        .println(GP-->invoke begin , execute method is                                 + method.getName() + , args is                                 + Arrays.asList(args));                Object obj = method.invoke(calculation, args);                return obj;            }        };        proxy = (Calculation) Proxy.newProxyInstance(loader, interfaces, h);        return proxy;    }}

The implementation of the dynamic proxy class, when implementing the invoke method, we output the log before calling the target method.

Test

public class Main {    public static void main(String[] args) {        Calculation calculation = new CalculationImpl();        CalculationProxy calculationProxy = new CalculationProxy(calculation);        Calculation cal = calculationProxy.getCalculationLog();        System.out.println(cal.add(1, 3));        System.out.println(cal.mul(1, 5));    }}

Output result

GP-> invoke begin, execute method is add, args is [1, 3]
4
GP-> invoke begin, execute method is mul, args is [1, 5]
5

It seems that it is much clearer. We extract logs to the dynamic proxy method separately, without interfering with the core business methods, and it is also easy for us to maintain.

Introduction to AOP

AOP (Aspect-Oriented Programming): a new methodology that complements traditional OOP (Object-Oriented Programming.
The main programming object of AOP is the aspect (aspect), while the aspect modular cross-cutting concerns.
When applying AOP programming, you still need to define public functions, but you can clearly define where the function is to be applied and how it is applied without modifying the affected classes. in this way, the cross-cutting concerns are modularized into special objects (slices.
Benefits of AOP:

Each transaction logic is located in one location, and the code is not scattered, so it is easier to maintain and upgrade the business module. It only contains the core business code. AOP terminology.

Aspect (Aspect): A special object that is modularized by a cross-concern (the function that spans multiple modules of an application ).
Advice
Target: the object to be notified.
Proxy: the object created after the notification is applied to the target object
Joinpoint: a specific position of a program execution, such as before, after, or after a method is called. The connection point is determined by two types of information: the execution point represented by the method, and the orientation indicated by the relative point. For example, the connection point before the ArithmethicCalculator # add () method is executed. The execution point is ArithmethicCalculator # add (). The orientation is the position before the method is executed.
Pointcut: each class has multiple connection points. For example, all methods of ArithmethicCalculator are actually connection points, that is, the connection points are objective transactions in the program class. AOP locates a specific connection point by cutting points. Analogy: A connection point is equivalent to a record in a database, and a cut point is equivalent to a query condition. A cut point and a connection point are not one-to-one relationships. A cut point matches multiple connection points and is described through the org. springframework. aop. Pointcut interface. It uses classes and methods as the query conditions for the connection points.

Aspect-based AOP-pre-notification

For more information, see: http://jinnianshilongnian.iteye.com/blog/1420689

JAR packages involved
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.RELEASE.jar
Commons-logging-1.1.1.jar
Spring-aop-4.1.7.RELEASE.jar
Spring-aspects-4.1.7.RELEASE.jar
Spring-beans-4.1.7.RELEASE.jar
Spring-context-4.1.7.RELEASE.jar
Spring-core-4.1.7.RELEASE.jar
Spring-expression-4.1.7.RELEASE.jar

Check the code

public interface Calculation {    public int add(int x, int y);    public int sub(int x, int y);    public int mul(int x, int y);    public int dev(int x, int y);}
@Componentpublic class CalculationImpl implements Calculation {    @Override    public int add(int x, int y) {        int result = x + y;        return result;    }    @Override    public int sub(int x, int y) {        int result = x - y;        return result;    }    @Override    public int mul(int x, int y) {        int result = x * y;        return result;    }    @Override    public int dev(int x, int y) {        int result = x / y;        return result;    }}

And Mark @ Component as a Component in the IOC container.

    
      

The path of the package to which the scan annotation is added.
By default, Spring does not support the @ AspectJ style section declaration and adds aspectj-autoproxy, so that Spring can discover the @ AspectJ style section and apply the section to the target object.

@Aspect@Componentpublic class CalculationAspect {    @Before(execution(public int com.gp.spring.aop.impl.Calculation.add(int, int)))    public void beforeMethod(JoinPoint joinPoint) {        String name = joinPoint.getSignature().getName();        List list = Arrays.asList(joinPoint.getArgs());        System.out.println(Method begin ... ,method= + name + , args =                 + list);    }}
CalculationAspect is marked as a Component and registered to the IOC container @ Aspect tag. spring configures it with AOP and generates the corresponding proxy class @ Before, which is a pre-notification, notification "execution (public int com. gp. spring. aop. impl. calculation. add (int,
Int) "expression, indicating the information about the package path and method to be executed for this notification. This expression can be used for fuzzy match, such as "execution (public int
Com. gp. spring. aop. impl. Calculation. * (*) ", indicating all methods in the Calculation class. The JoinPoint joinPoint parameter in the method indicates the connection point. This parameter can be used to obtain information about the execution method, such as the method name and method parameter.

Test Method

    public static void main(String[] args) {        ApplicationContext context = new ClassPathXmlApplicationContext(applicationContext.xml);        Calculation calculation = (Calculation)context.getBean(calculationImpl);        int result = calculation.add(3, 4);        System.out.println(result);    }

Output result

Method begin... , Method = add, args = [3, 4]
7

Aspect-based AOP-post notification

The post-notification method is similar to the pre-notification method. The difference is that the post-notification method is executed after the method is executed.

The Code is as follows:

    @After(execution(public int com.gp.spring.aop.impl.Calculation.add(int, int)))    public void afterMethod(JoinPoint joinPoint) {        String name = joinPoint.getSignature().getName();        List list = Arrays.asList(joinPoint.getArgs());        System.out.println(Method end ... ,method= + name + , args =                 + list);    }

The @ After annotation is used here. Nothing else has changed.

The test output result is as follows:

Method begin... , Method = add, args = [3, 4]
Executeing...
Method end... , Method = add, args = [3, 4]
7

I have added an output to the add method to distinguish between pre-notifications and post-notifications.

    public int add(int x, int y) {        int result = x + y;        System.out.println(executeing ...);        return result;    }
Aspect-based AOP-return notification

After the method is successfully executed, a notification is returned. If the method throws an exception during running, it is not called.

Code

    @AfterReturning(value = execution(public int com.gp.spring.aop.impl.Calculation.add(int, int)), returning = ret)    public void afterReturnMethod(JoinPoint joinPoint, Object ret) {        String name = joinPoint.getSignature().getName();        List list = Arrays.asList(joinPoint.getArgs());        System.out.println(@AfterReturning ... ,method= + name + , args =                 + list + , return =  + ret);    }

Different from post-notification, post-notification will still be called if an exception is thrown in the method. here we can use try... Catch... Analogy.

Output result

@ Before... , Method = add, args = [3, 4]
Executeing...
@ After... , Method = add, args = [3, 4]
@ AfterReturning... , Method = add, args = [1, 3], return = 4
7

Aspect-based AOP-exception notification

If an exception is thrown during running of the method, an exception notification is called.

Code

    @AfterThrowing(value = execution(public int com.gp.spring.aop.impl.Calculation.*(int, int)), throwing = ex)    public void afterThrowMethod(JoinPoint joinPoint, Exception ex) {        System.out.println(@AfterThrowing ... ,ex =  + ex);    }

Here is a little different from the previous usage. throwing is added to the annotation parameter, and the exception to be captured is added to the method. This is similar to try... Catch... Block in the catch

Output result

Exception in thread "main" @ AfterThrowing... , Ex = java. lang. ArithmeticException:/by zero
Java. lang. ArithmeticException:/by zero
At com. gp. spring. aop. impl. CalculationImpl. dev (CalculationImpl. java: 29)

Aspect-based AOP-surround notification

The surround notification is similar to the dynamic proxy described at the beginning. In this notification, you can call the target method, perform Various notifications (frontend, return, post, exception, etc.) on the upstream and downstream of the target method)

Code:

@ Around (execution (public int com. gp. spring. aop. impl. calculation. add (int, int) public Object aroundMethod (ProceedingJoinPoint pjd) {String name = pjd. getSignature (). getName (); ListList = Arrays. asList (pjd. getArgs (); Object obj = null; System. out. println (pre-notification ..., method = + name +, args = + list); try {obj = pjd. proceed (); System. out. println (return notification ..., method = + name +, args = + list);} catch (Throwable e) {System. out. println (abnormal notification ..., exception = + e); e. printStackTrace ();} System. out. println (post notification ..., method = + name +, args = + list); return obj ;}

Returned results:

Pre-notification... , Method = add, args = [1, 3]
Executeing...
Return notification... , Method = add, args = [1, 3]
Post notification... , Method = add, args = [1, 3]
4

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.