Section oriented thinking of spring AOP

Section oriented thinking of spring AOP

Three ideas of spring
IOC control reverse
DI dependency injection
AOP (Aspect Oriented Programming) makes up for the shortage of object-oriented programming

It is realized by precompiling and runtime dynamic agent
A technique for unified maintenance of sequential functions.
AOP is the continuation of OOP, a hot spot in software development, and an important part of Spring framework. Using AOP, we can make a clear understanding of business logic
The isolation of each part reduces the coupling degree between the parts of business logic, improves the reusability of the program, and improves the efficiency of development.

The benefits of doing so are:

  1. Enhance methods without modifying source code during program operation
  2. The logic is clear. When developing the core business, you don't need to pay attention to the code to enhance the business
  3. Reduce repetitive code, improve development efficiency and facilitate later maintenance

AOP related concepts

Target: the target object of the proxy
Proxy: when a class is enhanced by AOP weaving, a result proxy class is generated
Join point: the so-called join points refer to those intercepted points. In spring, these points refer to methods, because spring only supports connection points of method type
Pointcut: the so-called pointcut refers to the definition of which joinpoints we want to intercept
Advice (notification / enhancement): the so-called notification refers to the classification of notifications after intercepting Joinpoint: pre notification, post notification, exception notification, final notification and surround notification
Aspect: a combination of pointcuts and notifications
Weaving: refers to the process of applying enhancements to the target object to create a new proxy object. spring uses dynamic proxy weaving, while AspectJ uses compile time weaving and class load time weaving

OOP object oriented programming class
Let's take a brief look at aop through the code

Create a maven project

Implementation: call the service layer through the controller layer and then call the dao layer.
Create a maven project and lead the package (Note: change junit package version to 4.12 or higher),
Create a package level and run it to see if it can go through.
Create under resources applicationContext.xml configuration file
For example, create a bean class in the pojo package

package com.lanou.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value = "user")
public class User {
    @Value(value = "123")
    private int id;
    @Value("Zhang Sanfeng")
    private String username;
    @Value("123456")
    private String password;
	//setter getter with or without parameters toString method
}

For example, dao layer
Interface

import com.lanou.pojo.User;
import java.util.List;

public interface UserDao {
    List<User> findAll();
    User findUserById(int id);
    int updateUser(User user);
    int deleteUser(int id);
}

Implementation class

import com.lanou.dao.UserDao;
import com.lanou.pojo.User;
import org.springframework.stereotype.Repository;

import java.util.List;
@Repository(value = "userDao")
public class UserDaoImpl implements UserDao {
    @Override
    public List<User> findAll() {
        System.out.println("---------dao findAll Executed--------");
        return null;
    }
    @Override
    public User findUserById(int id) {
        return null;
    }
    @Override
    public int updateUser(User user) {
        return 0;
    }
    @Override
    public int deleteUser(int id) {
        return 0;
    }
}

For example, the service layer

import com.lanou.pojo.User;

import java.util.List;

public interface UserService {
    List<User> findAll();
    User findUserById(int id);
    int updateUser(User user);
    int deleteUser(int id);
}

service implementation class

import com.lanou.dao.UserDao;
import com.lanou.pojo.User;
import com.lanou.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;


import java.util.List;
@Service(value = "userService")
public class UserServiceImpl implements UserService {
    @Autowired
    @Qualifier(value = "userDao")
    private UserDao userDao;
    @Override
    public List<User> findAll() {
        return userDao.findAll();
    }

    @Override
    public User findUserById(int id) {
        return null;
    }

    @Override
    public int updateUser(User user) {
        return 0;
    }

    @Override
    public int deleteUser(int id) {
        return 0;
    }
}

For example: control layer


import com.lanou.pojo.User;
import com.lanou.service.Impl.UserServiceImpl;
import com.lanou.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

import java.util.List;

@Controller(value = "userController")
public class UserController {
    @Autowired
    @Qualifier(value = "userService")
    private UserService userService;
    public void findAll(){
        System.out.println("Before executing the current method");
        List<User> userList = userService.findAll();
        System.out.println("End of method execution");
    }
}

In the test class:

import com.lanou.controller.UserController;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestSpringJUnit {
    @Autowired
    @Qualifier(value = "userController")
    private UserController userController;
    @Test
    public void findAll() {
        userController.findAll();
    }
}

Easy to walk

Section programming based on xml file

jar packages to be imported to use aop

spring-aop
spring-aspects
aopalliance
aspectjweaver

The dependent jar package will be imported automatically in maven
So you only need to find the two jar packages of spring aspects and aopalliance in maven library

<!--aop Required for tangent programming jar package-->
    <!--aop-->
    <!--aspects-->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.1.14.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
    <dependency>
      <groupId>aopalliance</groupId>
      <artifactId>aopalliance</artifactId>
      <version>1.0</version>
    </dependency>

Define a facet class in the utils package

/*
Log facet class
 */

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

//Declare that the current class is a tangent class
public class LogAdvice {
    /*
    Section method
    Pre notification method
     */
    public void before(){
        System.out.println("--Before advice ----");
    }
    /*
    Section method
    The post notification method returns whether it is abnormal or not
     */
    public void after(){
        System.out.println("--Post notice----");
    }
    /*
    Post notification if exception does not return value
     */
    public void afterReturning(){
        System.out.println("---Post notice--No abnormality-");
    }
    /*
    Post notification exception return
     */
    public void afterException(){
        System.out.println("--Post notice--Exception notification--");
    }
    /*
    Around Advice 
     */
    public Object around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("Around Advice --Before advice ");
        Object object = point.proceed();//Continue calling target method
        System.out.println("Around Advice --Post notice");
        return object;
    }

}

Configuring in an xml 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"      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 https://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:annotation-config></context:annotation-config>
    <context:component-scan base-package="com.lanou"></context:component-scan>
   
    <!--Define section information-->
<bean id="logAdvice" class="com.lanou.utils.LogAdvice2"></bean>
    <!--Defining entry points-->
    <aop:config>
        <!--
        //breakthrough point
        id : name
        expression : Expression found package, class, method
        execution(* com.lanou.service.*.*(..))
        //Return value type of the first * method
        com.lanou.service Package name
        //Second * class name
        //Third * method name
        (..)  Any parameter
        -->
        <aop:pointcut id="pc" expression="execution(* com.lanou.service.*.*(..))"/>
        <!--Define associated facets-->
        <aop:aspect ref="logAdvice">
            <aop:before method="before" pointcut-ref="pc"></aop:before>
            <aop:after method="after" pointcut-ref="pc"></aop:after>
            <aop:after-returning method="afterReturning" pointcut-ref="pc"></aop:after-returning>
            <aop:after-throwing method="afterException" pointcut-ref="pc"></aop:after-throwing>
            <aop:around method="around" pointcut-ref="pc"/>
        </aop:aspect>
    </aop:config>
</beans>

Running the test method in the test class can see that the pre notification is performed before the core logic is executed, and the circular notification is performed. oop feels vertical, but aop seems to cut you horizontally. In addition to the enhanced business you want to perform (pre notification belongs to enhanced business), you need to perform pre business before performing core business (dao findAll core business)

Annotation based AOP

Open annotation in xml file
(Note: when I open annotation, I give the annotation the xml configuration, because when I test, I feel that the priority of xml configuration is higher than that of annotation.)

	<!--open aop annotation-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

Annotate LogAdvice in utils package

/*
Log facet class
 */

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component(value = "logAdvice")
//Declare that the current class is a tangent class
@Aspect
public class LogAdvice {
	/*
	If the expressions are the same, you don't need to configure anything else,
	You can add @ Pointcut("execution(* com.lanou.service .*.*(..))")
	Comments to be added every time around“ LogAdvice.pc() "you don't have to configure it every time
	*/
    @Pointcut("execution(* com.lanou.service.*.*(..))")
    public void pc(){

    }

    /*
    Section method
    Pre notification method
    Every time you have to follow an expression, do you have a method? If the expressions are the same, you don't need to configure other
     */
    @Before("LogAdvice.pc()")
    public void before(){
        System.out.println("--Before advice ----");
    }
    /*
    Section method
    The post notification method returns whether it is abnormal or not
    
     */
    @After("execution(* com.lanou.service.*.*(..))")
    public void after(){
        System.out.println("--Post notice----");
    }
    /*
    Post notification if exception does not return value
     */
    @AfterReturning("execution(* com.lanou.service.*.*(..))")
    public void afterReturning(){
        System.out.println("---Post notice--No abnormality-");
    }
    /*
    Post notification exception return
     */
    @AfterThrowing("execution(* com.lanou.service.*.*(..))")
    public void afterException(){
        System.out.println("--Post notice--Exception notification--");
    }
    /*
    Around Advice 
     */
    @Around("execution(* com.lanou.service.*.*(..))")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("Around Advice --Before advice ");
        Object object = point.proceed();//Continue calling target method
        System.out.println("Around Advice --Post notice");
        return object;
    }
}

Call test method: configuration in xml is an effect

Some concepts of AOP

Tags: Spring xml Programming Java

Posted on Sun, 07 Jun 2020 23:31:20 -0400 by sennetta