Spring AOP knowledge point mind map

What is the AOP?

AOP(aspect-oriented Programming), the name and OOP(object-oriented Programming) is only one letter, in fact, it is a supplement to OOP Programming. AOP translates as section-oriented programming, and the core is this aspect. The aspect represents the cross-cutting logic that is separated from the business logic, such as performance monitoring, logging, permission control, and so on, which can be separated from the core business logic code. That is, AOP solves the problem of code coupling and makes responsibility more monolithic.

To understand the concept, here is a transfer service:

Public interface IAccountService {// Main service logic: void Transfer (); } public class AccountServiceImpl implements IAccountService { @Override public voidtransfer() {
        System.out.println("Call the DAO layer to complete the main transfer business."); }}Copy the code

Now there is a requirement to verify the user’s identity before transferring money, so we usually just change the source code:

public class AccountServiceImpl implements IAccountService {
    @Override
    public void transfer() {
	  System.out.println("Verify the identity of the transferor.");

        System.out.println("Call the DAO layer to complete the main transfer business."); }}Copy the code

But as “experienced” Java developers, we know that “authentication” is a business that can be completely stripped away, so we use the idea of the proxy design pattern:

Public class AccountProxy implements IAccountService {// Target object private IAccountService Target; public AccountProxy(IAccountService target) { this.target = target; } /** * Override public voidtransfer() { before(); target.transfer(); } /** * authentication */ private voidbefore() {
        System.out.println("Verify the identity of the transferor."); }} public class Client {public static void main(String[] args) {IAccountService Target = new AccountServiceImpl(); // Create a proxy object AccountProxy proxy = new AccountProxy(target); proxy.transfer(); }}Copy the code

Principle of AOP is the proxy design pattern and the above is the static, but Spring AOP are implemented by dynamic proxy, so we need to know the dynamic proxy: blog.csdn.net/litianxiang…

AOP was not invented by Spring. Before Spring, there was AspectJ, an open source framework for AOP, and AspectJ’s AOP was more powerful than Spring’s, so AspectJ was integrated in a later version of Spring. But it’s important to take a look at Spring’s AOP capabilities.

AOP terminology

  • Targe Target object
  • Joinpoint join points, all methods that can be enhanced are join points.
  • The Pointcut Pointcut, the method to be enhanced.
  • Advice enhancement, crosscutting logic separated from the main business logic.
  • Aspect aspects, pointcuts plus enhancements are aspects.
  • Weaving refers to the process of applying a cut to a target.
  • Proxy Indicates the enhanced target object.

Advice Common types

  • Lead to enhance org. Springframework. Aop MethodBeforeAdvice, – in the target method performs before implementation.
  • Rear enhance org. Springframework. Aop. AfterReturningAdvice, implemented after the target method was implemented.
  • Surrounding the enhanced org. Aopalliance. Intercept MethodInterceptor, method execution on the target before and after implementation.
  • Exception thrown enhance org. Springframework. Aop. ThrowsAdvice, implementation of the enhanced after method throws an exception.
  • Introduced to enhance org. Springframework. Aop IntroductionInterceptor, to enhance class, namely in the target class to add some new methods and properties.

Spring AOP programming

Let’s get a feel for Spring AOP programmatically. The following example uses wrap enhancement.

(1) business class

Public interface IAccountService {// Main service logic: void Transfer (); } public class AccountServiceImpl implements IAccountService { @Override public voidtransfer() {
        System.out.println("Call the DAO layer to complete the main transfer business."); }}Copy the code

(2)

public class AccountAdvice implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        before();
        Object result = invocation.proceed();
        after();
        return result;
    }

    private void before() {
        System.out.println("Before");
    }

    private void after(){
        System.out.println("After"); }}Copy the code

(3) test

Public class Test {public static void main(String[] args) {// Create ProxyFactory ProxyFactory = new ProxyFactory(); // Configure the target object proxyFactory.settarget (new AccountServiceImpl()); // Configure enhanced proxyFactory.addadvice (new AccountAdvice()); IAccountService proxy = (IAccountService) proxyFactory.getProxy(); proxy.transfer(); }} Result: Before invokes the DAO layer to complete the main transfer business. AfterCopy the code

Declarative Spring AOP

Spring AOP’s declarative approach is to use configuration files to declare various beans.

(1) business class

Public interface IAccountService {// Main service logic: void Transfer (); } public class AccountServiceImpl implements IAccountService { @Override public voidtransfer() {
        System.out.println("Call the DAO layer to complete the main transfer business."); }}Copy the code

(2)

public class AccountAdvice implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        before();
        Object result = invocation.proceed();
        after();
        return result;
    }

    private void before() {
        System.out.println("Before");
    }

    private void after(){
        System.out.println("After"); }}Copy the code

(3) Configuration file

<? 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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <! --> <bean id="accountService" class="org.service.impl.AccountServiceImpl"></bean>
    <bean id="accountAdvice" class="org.aspect.AccountAdvice"></bean> <! -- Configure proxy factory --> <bean id="accountProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <! -- Target interface --> <property name="interfaces" value="org.service.IAccountService"/ > <! -- Target object --> <property name="target" ref="accountService"/ > <! -- enhanced --> <property name="interceptorNames" value="accountAdvice"/>
    </bean>

</beans>
Copy the code

(4) test

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-service.xml");
        IAccountService proxy = (IAccountService) context.getBean("accountProxy"); proxy.transfer(); }} Result: Before invokes the DAO layer to complete the main transfer business. AfterCopy the code

Aspects of Spring AOP

The previous programmatic and declarative versions do not use aspects; they implement enhancements for all methods in a class. If we need to enhance a method in a class, we can use aspects to solve this problem.

Modify the configuration file based on the declarative code by adding facets:

<? 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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <! --> <bean id="accountService" class="org.service.impl.AccountServiceImpl"></bean>
    <bean id="accountAdvice" class="org.aspect.AccountAdvice"></bean> <! -- Config section --> <bean id="accountAspect" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <! -- enhanced --> <property name="advice" ref="accountAdvice"/ > <! -- pointcut --> <property name="pattern" value="org.service.impl.AccountServiceImpl.transfer.*"/> </bean> <! -- Configure proxy --> <bean id="accountProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <! -- Target object --> <property name="target" ref="accountService"/ > <! --> <property name="interceptorNames" value="accountAspect"/>
    </bean>

</beans>
Copy the code

Here the aspect configuration is based on the regular expression RegexpMethodPointcutAdvisor, said intercept all begin with the “transfer” method. In addition, Spring AOP has the following configurations:

  • Org. Springframework. Aop. Support. Matching DefaultPointcutAdvisor inherited the class section.
  • Org. Springframework. Aop. Support. NameMatchMethodPointcutAdvisor according to the method name match.
  • Org. Springframework. Aop. Support. StaticMethodMatcherPointcutAdvisor used to match a static method.

Automatic proxy for Spring AOP

It may seem acceptable to let the user configure one or a few agents, but as the project grows, there will be more and more agents, and it will be bad for you to manually configure them. But don’t worry, Spring AOP gives us the ability to automatically generate proxies.

Modify configuration files and test classes based on declarative code:

(1) Configuration file

<? 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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <! --> <bean id="accountService" class="org.service.impl.AccountServiceImpl"></bean>
    <bean id="accountAdvice" class="org.aspect.AccountAdvice"></bean> <! -- Config section --> <bean id="accountAspect" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <! -- enhanced --> <property name="advice" ref="accountAdvice"/ > <! -- pointcut --> <property name="pattern" value="org.service.impl.AccountServiceImpl.transfer.*"/> </bean> <! Configure automatic proxy: automatically scan all aspect classes and generate proxies for them --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
</beans>
Copy the code

(2) test

public class Test{
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-service.xml");
        IAccountService proxy = (IAccountService) context.getBean("accountService"); proxy.transfer(); }} Result: Before invokes the DAO layer to complete the main transfer business. AfterCopy the code

Spring + AspectJ

In enterprise development, the use of AspectJ instead of Spring’s own AOP capabilities is rarely used. Spring’s own integration with AspectJ later proves the power of AspectJ indirectly. Let’s look at Spring + AspectJ.

AspectJ enhanced types

  • < AOP: Before >
  • Post-enhanced annotation: @after, configuration: < AOP: After >
  • Annotation: @around, configuration: < AOP: Around >
  • Exception throwing enhanced annotation: @afterthrowing, configuration: < AOP :after-throwing>
  • Introduce enhanced annotation: @declareparents, configuration: < AOP :declare-parents> pointcut expression
execution(* org.service.impl.AccountServiceImpl.*(..) )Copy the code
  • Execution () represents the interception method, with the rules to be matched defined in parentheses.
  • The first “*” indicates that the return value of the method is arbitrary.
  • The second “*” matches all methods in the class.
  • (…). The parameters that represent the method are arbitrary. As you can see, AspectJ’s pointcut expressions are much more readable than Spring AOP’s regular expressions.

Spring AspectJ instance – based on configuration

(1) business class

Public interface IAccountService {// Main service logic: void Transfer (); } public class AccountServiceImpl implements IAccountService { @Override public voidtransfer() {
        System.out.println("Call the DAO layer to complete the main transfer business."); }}Copy the code

(2)

Public class AccountAdvice{public void myBefore(JoinPoint JoinPoint){before(); } public void myAfter(JoinPoint JoinPoint) {after(); } public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{before(); Object result = joinPoint.proceed(); after();returnresult; Public void myThrowing(JoinPoint JoinPoint, Throwable e) {system.out.println ("Throw exception enhancement:" + e.getMessage());
    }


    private void before() {
        System.out.println("Before");
    }

    private void after(){
        System.out.println("After"); }}Copy the code

(3) the configuration

<? 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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <! --> <bean id="accountService" class="org.service.impl.AccountServiceImpl"></bean>
    <bean id="accountAdvice" class="org.aspect.AccountAdvice"></bean> <! <aop:config> <aop:aspect ref="accountAdvice"> <! Aop :pointcut expression="execution(* org.service.impl.AccountServiceImpl.*(..) )" id="myPointCut"/ > <! Aop :around method="myAround" pointcut-ref="myPointCut"/>
        </aop:aspect>
    </aop:config>
</beans>
Copy the code

(4) test

public class Test{
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-service.xml");
        IAccountService proxy = (IAccountService) context.getBean("accountService"); proxy.transfer(); }} Result: Before invokes the DAO layer to complete the main transfer business. AfterCopy the code

Spring AspectJ instance – annotation-based

(1) business class

Public interface IAccountService {// Main service logic: void Transfer (); } @Component public class AccountServiceImpl implements IAccountService { @Override public voidtransfer() {
        System.out.println("Call the DAO layer to complete the main transfer business."); }}Copy the code

(2) section

It’s no longer called enhancement, because with pointcuts and enhancements, it’s better to call aspects.

@component@aspect public class AccountAspect{// Pointcut @pointcut ("execution(* org.tyshawn.service.impl.AccountServiceImpl.*(..) )")
    private void pointCut() {}; // add @before ("pointCut()") public void myBefore(JoinPoint joinPoint){ before(); } // After("pointCut()")
    public void myAfter(JoinPoint joinPoint) {
        after();
    }

    //环绕增强
    @Around("pointCut()")
    public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
        before();
        Object result  = joinPoint.proceed();
        after();
        returnresult; } // Throw exception enhancement @afterthrowing (value ="pointCut()", throwing = "e")
    public void myThrowing(JoinPoint joinPoint, Throwable e) {
        System.out.println("Throw exception enhancement:" + e.getMessage());
    }

    private void before() {
        System.out.println("Before");
    }

    private void after(){
        System.out.println("After"); }}Copy the code

(3) the configuration

<? 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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <! <context:component-scan base-package="org.tyshawn"></context:component-scan> <! Aop :aspectj-autoproxy </aop:aspectj-autoproxy> </beans>Copy the code

(4) test

public class Test{
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring-service.xml");
        IAccountService proxy = (IAccountService) context.getBean("accountServiceImpl"); proxy.transfer(); }} Result: Before Before The DAO layer is invoked to complete the main transfer business. After AfterCopy the code

Source: t.i m/KZFR

Open Source Project Recommendation

The authors recommend open source projects:

  • Pre Is a RBAC permission management system based on Spring Boot, Spring Security, and Vue
  • Prex based on Spring Cloud, Oauth2, Vue of the front and back end separation of the microservice architecture RBAC permission management system

Concern public number reply open source project can be obtained