1. What is AOP
AOP is the abbreviation of Aspect Oriented Programming, which means aspect-oriented programming. AOP is actually a continuation of the GoF design model.
2. Some terms about Spring AOP:
A. Aspect: In Spring AOP, the facet can be implemented using a general class or in a normal class with @Aspect annotation (@AspectJ style)
B. Joinpoint: In Spring AOP, a connection point represents the execution of a method.
C. Advice: An action performed on a specific joint point on the section. There are various types of notifications, including "around", "before" and "after". Many AOP frameworks, including Spring, use interceptors as notification models and maintain a link point-centered interceptor chain.
D. Pointcut: Define one or a group of methods, which can generate notifications when executing these methods. Spring uses AspectJ point-cut syntax by default.
3. Notification Type
A. Pre-notification (@Before): A notification executed before a join point, but this notification cannot prevent execution before the connection point (unless it throws an exception)
B. Notification after return (@AfterReturning): Notification executed after a connection point (join point) is completed normally: For example, a method does not throw any exception and returns normally
C. Notification after the exception is thrown (@AfterThrowing): Notification executed when the method throws the exception and exits
D. Post notification (@After): Notification executed when a connection point exits (whether it is a normal return or an abnormal exit)
E. Surround notification (@Around): Notifications surrounding a join point, such as method calls. This is the most powerful notification type, and surround notifications can complete custom behavior before and after method calls. It also chooses whether to continue executing the connection points or directly return their own return value or throw an exception to end the execution
4. @AspectJ style AOP configuration
Spring AOP configuration has two styles:
A. XML style = Implement Spring AOP in declarative form
B. AspectJ style = Implement Spring AOP using annotation form
5. Example
TestAspect
package com.spring.aop; /** * Section*/ public class TestAspect { public void doAfter(JoinPoint jp) { System.out.println("log Ending method: " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName()); } public Object doAround(ProceedingJoinPoint pjp) throws Throwable { long time = System.currentTimeMillis(); Object retVal = pjp.proceed(); time = System.currentTimeMillis() - time; System.out.println("process time: " + time + " ms"); return retVal; } public void doBefore(JoinPoint jp) { System.out.println("log Begining method: " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName()); } public void doThrowing(JoinPoint jp, Throwable ex) { System.out.println("method " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName() + " throw exception"); System.out.println(ex.getMessage()); } private void sendEx(String ex) { //TODO Send SMS or Email Reminder} } package com.spring.service; /** * Interface A */ public interface AService { public void fooA(String _msg); public void barA(); } package com.spring.service; /** *Implementation class of interface A*/ public class AServiceImpl implements AService { public void barA() { System.out.println("AServiceImpl.barA()"); } public void fooA(String _msg) { System.out.println("AServiceImpl.fooA(msg:"+_msg+")"); } } package com.spring.service; /** * Service class B */ public class BServiceImpl { public void barB(String _msg, int _type) { System.out.println("BServiceImpl.barB(msg:"+_msg+" type:"+_type+")"); if(_type == 1) throw new IllegalArgumentException("Test Exception"); } public void fooB() { System.out.println("BServiceImpl.fooB()"); } }ApplicationContext
<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd" default-autowire="autodetect"> <aop:config> <aop:aspect id="TestAspect" ref="aspectBean"> <!--Configure all methods of all classes or interfaces under com.spring.service package--> <aop:pointcut id="businessService" expression="execution(* com.spring.service.*.*(..))" /> <aop:before pointcut-ref="businessService" method="doBefore"/> <aop:after pointcut-ref="businessService" method="doAfter"/> <aop:around pointcut-ref="businessService" method="doAround"/> <aop:after-throwing pointcut-ref="businessService" method="doThrowing"/> </aop:aspect> </aop:config> <bean id="aspectBean" /> <bean id="aService"></bean> </beans>
Test class AOPTest
public class AOPTest extends AbstractDependencyInjectionSpringContextTests { private AService aService; private BServiceImpl bService; protected String[] getConfigLocations() { String[] configs = new String[] { "/applicationContext.xml"}; return configs; } /** * Test normal call*/ public void testCall() { System.out.println("SpringTest JUnit test"); aService.fooA("JUnit test fooA"); aService.barA(); bService.fooB(); bService.barB("JUnit test barB",0); } /** * Test After-Throwing */ public void testThrow() { try { bService.barB("JUnit call barB",1); } catch (IllegalArgumentException e) { } } public void setAService(AService service) { aService = service; } public void setBService(BServiceImpl service) { bService = service; } }
The operation results are as follows:
log Begining method: com.spring.service.AServiceImpl.fooA AServiceImpl.fooA(msg:JUnit test fooA) log Ending method: com.spring.service.AServiceImpl.fooA process time: 0 ms log Begining method: com.spring.service.AServiceImpl.barA AServiceImpl.barA() log Ending method: com.spring.service.AServiceImpl.barA process time: 0 ms log Begining method: com.spring.service.BServiceImpl.fooB BServiceImpl.fooB() log Ending method: com.spring.service.BServiceImpl.fooB process time: 0 ms log Begining method: com.spring.service.BServiceImpl.barB BServiceImpl.barB(msg:JUnit test barB type:0) log Ending method: com.spring.service.BServiceImpl.barB process time: 0 ms log Begining method: com.spring.service.BServiceImpl.barB BServiceImpl.barB(msg:JUnit call barB type:1) log Ending method: com.spring.service.BServiceImpl.barB method com.spring.service.BServiceImpl.barB throw exception Test exception