Spring Learning Notes-DAY3

3.1 Spring AOP

3.1.1 What is AOP

Face-Oriented Programming (Aspect-Oriented Programming) is a supplement to Object-Oriented Programming.
AOP uses a horizontal extraction mechanism to extract duplicate code that is scattered across methods, and then applies the extracted code to where it needs to be executed when the program is compiled or run.This way of using the horizontal extraction mechanism is obviously impossible with the traditional OOP idea, within which OOP can only achieve the vertical reuse of parent-child relationship.Although AOP is a new programming idea, it is not a substitute for OOP, it is just an extension and supplement of OOP.
In AOP thinking, Aspect allows you to incorporate functions such as transactions, logs, permissions, and exceptions into methods of different classes.

3.1.2 AOP terminology

  • Aspect: In practice, facets are usually encapsulated classes used to horizontally insert system functions such as transactions, logs, etc. To be recognized as facets by the Spring container, they need to be specified in the configuration file through the < bean > element.
  • Joinpoint: A point at a certain stage in the execution of a program that is actually an operation of an object, such as a method call or an exception throw.In Spring AOP, a join point is a call to a method.
  • Pointcut: refers to the intersection of the facets and the process, that is, the connection points that need to be processed.In programs, a starting point is a class or method name, and if a notification is to be applied to all methods that begin with add, all methods that satisfy this rule are starting points.
  • Advice: The AOP framework performs enhancement at a specific entry point, which is the program code to be executed at a defined entry point.This can be understood as a method in the tangent class, which is a concrete implementation of the tangent.
  • Target Object: refers to all notified objects that are also enhanced.If the AOP framework uses a dynamic AOP implementation, then the object is a proxy object.
  • Proxy: An object created dynamically after notifications have been applied to the target object.
  • Weaving: The process of generating a proxy object by inserting facet code onto the target object.

3.2 AspectJ development

There are two ways to implement AOP using AspectJ: declarative AspetJ based on XML and declarative AspectJ based on annotations.

3.2.1 XML-based declarative AspectJ

XML-based declarative AspectJ refers to defining facets, entry points, and notifications through an XML file, all of which must be defined within the < aop:config> element.The < beans > element in the Spring configuration file can contain multiple < aop:config > elements, and one < aop:config > element can contain attributes and child elements, including < aop:pointcut>, < aop:advisor>, and < aop:aspect>.These three child elements must be defined in this order when configuring.The < aop:aspect> element and its children allow you to configure facets, entry points, and notifications in an XML file.

Common configuration codes:

<!-- Define Faces Bean -->
<bean id="myAspect" class="com.ssm.aspectj.xml.MyAspect/>
<aop:config>
		<!-- 1.Configure Faces -->
		<aop:aspect id="aspect" ref="myAspect">
			<!-- 2.Configure entry points -->
			<aop:pointcut expression="execution(* com.ssm.aspectj.*.*(..))" id="myPointCut"/>
			<!-- 3.Configuration Notifications -->
				<!-- Before advice -->
				<aop:before method="myBefore" pointcut-ref="myPointCut"/>
				<!-- after returning advise -->
				<aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="returnVal"/>
				<!-- Around Advice -->
				<aop:around method="myAround" pointcut-ref="myPointCut"/>
				<!-- Exception Notification -->
				<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e" />
				<!-- Final Notification -->
				<aop:after method="myAfter" pointcut-ref="myPointCut"/>
		</aop:aspect>
</aop:config>
  1. Configure Faces
    In Spring's configuration file, configuration facets use the <aop:aspect>element, which converts a defined Spring Bean into a faceted Bean, so define a common Spring Bean in the configuration file first, and then reference it through the ref attribute of the <aop:aspect>element when the definition is complete.
    When configuring an <aop:aspect>element, two attributes, id and ref, are usually specified.
Property Name describe
id Unique identification name used to define the facet
ref Used to reference plain Spring Bean s
  1. Configure entry points
    The entry point is defined by <aop:pointcut>
    When <aop:pointcut>is defined as a child element of <aop:config>, it means that the entry point is a global entry point that can be shared by multiple facets.
    When <aop:pointcut>is a child element of <aop:aspect>it means that the entry point is valid only for the current facet.
    When defining <aop:pointcut>, two attributes, id and expression, are usually specified.
Property Name describe
id Unique identification name used to define entry point
expression An entry point expression used to specify an entry point Association

execution(* com.ssm.aspectj. *. * (.)) is an entry point expression that matches the execution of any method of any class in the com.ssm.aspectj package.
Where execution is the body of the expression, the first * is the return type, with * representing all types; the second * is the class name, with * representing all classes; the third * is the method name, representing all methods; the following () is the parameter of the method, where'...'Represents any parameter.
The basic format of the entry point expression in Spring AOP is as follows:
execuion(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?

  • modifiers-pattern represents access modifiers that define the target method, such as public, private, and so on.
  • ret-type-pattern represents the return value type that defines the target method.
  • declaring-type-pattern represents the path that defines the target method.
  • name-pattern represents the target method that needs to be proxied.
  • The param-pattern represents the parameters contained by the target method that need to be proxied.
  • throws-pattern indicates the type of exception thrown by the target method that needs to be proxied.

A section with a question mark indicates an optional configuration item, while the rest belongs to a required configuration item.

  1. Configuration Notifications

Example 3-1

  1. Create a project and import a jar package.
    spring-aspects-5.2.2.RELEASE.jar
    aspectjweaver-1.8.10.jar

  2. Create the com.ssm.aspectj package, create the interface UserDao, and write add-delete methods.

package com.ssm.aspectj;

public interface UserDao {
    public void addUser();
    public void deleteUser();
}

  1. Create interface implementation class
package com.ssm.aspectj;

public class UserDaoImpl implements UserDao {
    public void addUser() {
        System.out.println("Add User");
    }
    public void deleteUser() {
        System.out.println("delete user");
    }
}

  1. Create the com.ssm.aspectj.xml package, create the facet class MyAspect, and define different types of notifications
package com.ssm.aspectj.xml;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

/**
 * Face class, where notifications are written
 */
public class MyAspect {
//    Before advice
    public void myBefore(JoinPoint joinPoint){
        System.out.println("Pre-notification: Simulate permission checking...");
        System.out.println("The target class is:"+joinPoint.getTarget());
        System.out.println(",The target methods for implanted enhancement are:"+joinPoint.getSignature().getName());
    }
//    after returning advise
    public void myAfterReturning(JoinPoint joinPoint){
        System.out.println("Post Notification: Simulate Logging...");
        System.out.println("The target methods for implanted enhancement are:"+joinPoint.getSignature().getName());
    }
    /**
     * Around Advice
     * ProceedingJoinPoint Is a subinterface of JoinPoint representing the executable target method
     * 1.Must be a return value of type Object
     * 2.Must receive a parameter of type ProceedingJoinPoint
     * 3.Must be throws Throwable
     */

    protected Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable  {
//        start
        System.out.println("Surround Start: Simulate open transactions before executing the target method...");
//        Execute current target method
        Object obj=proceedingJoinPoint.proceed();
//        End
        System.out.println("End of wrap: simulate closing transactions after executing the target method");
        return obj;
    }
//    Exception Notification
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("Exception Notification: Error"+e.getMessage());
    }
//    Final Notification
    public void myAfter(){
        System.out.println("Final Notification: Release resources after the simulation method has finished...");
    }
}

Five different types of notifications are defined, using the JoinPoint interface and its subinterface ProceedingJoinPoint as parameters to obtain the class name, target method name, target method parameters, and so on.

  1. Create applicationContext.xml
<?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.xsd
       http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop.xsd
">
<!--    1 Target Class-->
    <bean id="userDao" class="com.ssm.aspectj.UserDaoImpl"/>
<!--    2 section-->
    <bean id="myAspect" class="com.ssm.aspectj.xml.MyAspect"/>
<!--    3 aop programming-->
    <aop:config>
<!--        1.Configure Faces-->
        <aop:aspect id="aspect" ref="myAspect">
<!--            2.Configure entry points-->
            <aop:pointcut id="myPointCut" expression="execution(* com.ssm.aspectj.*.*(..))"/>
<!--            3.Configuration Notifications-->
<!--                Before advice-->
            <aop:before method="myBefore" pointcut-ref="myPointCut"/>
<!--                after returning advise-->
            <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut"/>
<!--                Around Advice-->
            <aop:around method="myAround" pointcut-ref="myPointCut"/>
<!--                Exception Notification-->
            <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>
<!--                Final Notification-->
            <aop:after method="myAfter" pointcut-ref="myPointCut"/>
        </aop:aspect>
    </aop:config>

</beans>
  1. Create test classes to enhance addUser
package com.ssm.aspectj.xml;

import com.ssm.aspectj.UserDao;
import com.sun.javafx.tools.ant.Application;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TsetXmlAspectJ {
    public static void main(String[] args){
//        Define Profile Path
        String xmlPath="com/ssm/aspectj/xml/applicationContext.xml";
        //Initialize Spring Container Load Profile
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);
        //Get UserDao instance from container
        UserDao userDao= (UserDao) applicationContext.getBean("userDao");
        //Execution Method
        userDao.addUser();
    }
}

Run Results

To see the effect of exception notification execution, you can add error code in addUser, such as int i=10/0

3.2.2 Annotation-based declarative AspectJ

XML-based declarative AspectJ is convenient for AOP programming, but it has some drawbacks and requires a lot of code information to be configured.
Annotation-based declarative AspectJ solves this problem.

Example 3-2

  1. Create the com.ssm.aspectj.annotation package, copy MyAspect under the package, and modify it
package com.ssm.aspectj.annotation;

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

/**
 * Face class, where notifications are written
 */
@Aspect
@Component
public class MyAspect {
    //Define an entry point expression
    @Pointcut("execution(* com.ssm.aspectj.*.*(..))")
    //Name the entry point using a method with a void return value and an empty method body
    public void myPointCut(){}
//    Before advice
    @Before("myPointCut()")
    public void myBefore(JoinPoint joinPoint){
        System.out.println("Pre-notification: Simulate permission checking...");
        System.out.println("The target class is:"+joinPoint.getTarget());
        System.out.println(",The target methods for implanted enhancement are:"+joinPoint.getSignature().getName());
    }
//    after returning advise
    @AfterReturning(value = "myPointCut()")
    public void myAfterReturning(JoinPoint joinPoint){
        System.out.println("Post Notification: Simulate Logging...");
        System.out.println("The target methods for implanted enhancement are:"+joinPoint.getSignature().getName());
    }
    /**
     * Around Advice
     * ProceedingJoinPoint Is a subinterface of JoinPoint representing the executable target method
     * 1.Must be a return value of type Object
     * 2.Must receive a parameter of type ProceedingJoinPoint
     * 3.Must be throws Throwable
     */
    @Around("myPointCut()")
    protected Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable  {
//        start
        System.out.println("Surround Start: Simulate open transactions before executing the target method...");
//        Execute current target method
        Object obj=proceedingJoinPoint.proceed();
//        End
        System.out.println("End of wrap: simulate closing transactions after executing the target method");
        return obj;
    }
//    Exception Notification
    @AfterThrowing(value = "myPointCut()",throwing = "e")
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("Exception Notification: Error"+e.getMessage());
    }
//    Final Notification
    @After("myPointCut()")
    public void myAfter(){
        System.out.println("Final Notification: Release resources after the simulation method has finished...");
    }
}

The @Aspect annotation is used to define the facet class first, and since it is used as a component in Spring, the @Component annotation is required to take effect.
Then use the @Pointcut comment to configure the cut-in expression and define a way to represent the name of the cut-in point.
A comment is added to each notification method and the entry point name "myPointcut" is passed as a parameter to the notification method that needs to be enhanced.

  1. Add the comment @Repository("userDao") to the target class UserDaoImpl
  2. Create applicationContext.xml
<?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       
">
<!--    Scan the specified package for the comment to take effect-->
<context:component-scan base-package="com.ssm"/>
<!--    Start annotation-based declarations AspectJ Support-->
    <aop:aspectj-autoproxy/>
</beans>

The context constraint information is first introduced.
The <context> element is then used to set the package that needs to be scanned for the annotation to take effect.
Finally, use <aop:aspectj-autoproxy/> to launch Spring's support for annotation-based declarative Aspect s.

  1. Create test class TestAnnotation in the com.ssm.aspectj.annotation package
package com.ssm.aspectj.annotation;

import com.ssm.aspectj.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAnnotation {
    public static void main (String[] args){
        String xmlPath="com/ssm/aspectj/annotation/applicationContext.xml";
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);
        UserDao userDao= (UserDao) applicationContext.getBean("userDao");
        userDao.addUser();
    }
}

8 original articles published. 1. 714 visits
Private letter follow

Tags: Spring xml Programming encoding

Posted on Sun, 12 Jan 2020 17:27:25 -0800 by JTapp