catalog
introduction
- What is AOP? (interview question), simply answering face-to-face programming can't satisfy the interviewer, it's better to combine your own understanding.
AOP overview
- AOP (aspect oriented programming): it is a new methodology and a supplement to traditional OOP (object oriented programming).
- Object oriented vertical inheritance mechanism
- Section oriented horizontal extraction mechanism
- The main object of AOP programming is aspect, which is used to modularize crosscutting concerns (i.e. common function Util)
- When applying AOP programming, you still need to define common functions, but you can clearly define where and how this function is applied, and you do not need to modify the affected classes. In this way, crosscutting concerns are modularized into special classes - such classes are often referred to as "facets.".
- The advantages of AOP are: (1) each transaction logic is located in one place, the code is not scattered, and it is easy to maintain and upgrade; (2) the business module is more concise, only including the core business code;
- AOP implementation is dependency Dynamic agent
- AOP diagram
AOP terminology
- Crosscutting concerns: the same kind of non core business extracted from each method
- Aspect: a class that encapsulates information about crosscutting concerns, each of which is represented as a notification method.
- Advice: the specific work that must be done in all aspects. (including: pre notice, post notice, return notice, exception notice, surround notice)
- Target: the notified object.
- Proxy: proxy object created after notification is applied to the target object
- Join point: the specific implementation of crosscutting concerns in program code, corresponding to a specific location of program execution. For example: before a method call, after a call, after a method catches an exception, etc. In the application, you can use horizontal and vertical coordinates to locate a specific connection point:
Understanding of hands through practice (simple calculator)
- Create a Java project, and then build the conf folder (put the xml configuration file), lib (put the jar package)
- jar package to import
- com.springsource.net.sf.cglib-2.2.0.jar
- com.springsource.org.aopalliance-1.0.0.jar
- com.springsource.org.aspectj.weaver-1.6.4.RELEASE.jar
- commons-logging-1.1.1.jar
- spring-aop-4.0.0.RELEASE.jar
- spring-aspects-4.0.0.RELEASE.jar
- spring-beans-4.0.0.RELEASE.jar
- spring-context-4.0.0.RELEASE.jar
- spring-core-4.0.0.RELEASE.jar
- spring-expression-4.0.0.RELEASE.jar
- The conf configuration file is as follows:
<?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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.test"/> <aop:aspectj-autoproxy/> </beans>
- Business logic layer
package com.test.Service; public interface MathService { //add , subtract , multiply and divide int add(int i, int j); int sub(int i, int j); int mul(int i, int j); int div(int i, int j); }
- Impl implementation layer
package com.test.Impl; import com.test.Service.MathService; import org.springframework.stereotype.Service; @Service public class MathImpl implements MathService { private int result; public int add(int i, int j){ this.result = i + j; return result; } public int sub(int i, int j){ this.result = i - j; return result; } public int mul(int i, int j){ this.result = i * j; return result; } public int div(int i, int j){ this.result = i / j; return result; } }
- So called crosscutting concerns (public functions: like logging)
package com.test.Logger; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Component @Aspect public class MyLoggerAspect { @Before(value="execution(* com.test.Impl.MathImpl.*(..))") public void beforeMethod(){ System.out.println("Before advice "); } @After(value="execution(* com.test.Impl.MathImpl.*(..))") public void afterMethod(){ System.out.println("Post notice"); } @AfterReturning(value="execution(* com.test.Impl.MathImpl.*(..))", returning = "result") public void afterReturning(JoinPoint joinPoint, Object result){ String methodName = joinPoint.getSignature().getName(); System.out.println("method:"+methodName+"\tresult:" + result); } @AfterThrowing(value="execution(* com.test.Impl.MathImpl.*(..))", throwing = "ex") public void afterThrowingMethod(ArithmeticException ex){ System.out.println("Exception information: " + ex); } /** * In this case, circular notification is equivalent to integrating the front, * You can try to comment out the front, just use this paragraph * @Around(value="execution(* com.test.Impl.MathImpl.*(..))") * public Object aroundMethod(ProceedingJoinPoint joinPoint){ * try { * System.out.println("Pre notice '); * joinPoint.proceed(); * } catch (Throwable e) { * e.printStackTrace(); * System.out.println("Exception notification '); * }finally { * System.out.println("Post notification '); * } * //Why not return null here? Because the receiving object is Integer * return -1; * } */ }
- Test slice priority
package com.test.Logger; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Aspect @Order(1)//@The lower the value of order, the higher the priority. The default value is the maximum value of Int public class TestAspect { @Before(value="execution(* com.test.Impl.MathImpl.*(..))") public void before(){ System.out.println("I have a higher priority==>Before advice "); } }
- Test class
package com.test; import com.test.Service.MathService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyProxyTest { public static void main(String[] args) { ApplicationContext ac =new ClassPathXmlApplicationContext("config.xml"); MathService mathService = ac.getBean("mathImpl",MathService.class); mathService.div(4,2); } }
All the codes of the simple calculator