Spring's core AOP and proxy pattern ("easiest to understand spring learning")

🏇 wow Click Click : \textcolor{blue} {wow, Kaka:} Wow, Kaka: stay front two piece in I Guys Yes solution Yes I O C \textcolor{green} {in the first two articles, we learned about IOC} In the first two articles, we learned about IOC
🏇 meet lower come Just meet touch one lower another one individual nucleus heart A O P \textcolor{pink} {next, let's touch on another core AOP} Next, let's touch on another core AOP
💥The code used can be found here💥
🙏 Bo main also stay learn Learn rank paragraph , as if hair present ask topic , please Tell know , wrong often sense thank \textcolor{Orange} {blogger is also in the learning stage. If you find any problems, please let me know. Thank you very much} Bloggers are also in the learning stage. If you find any problems, please let us know. Thank you very much 💗

🐳 Click to send you to "a brief understanding of the theoretical derivation of Spring and IOC"
🐳 Click to send you to IOC and DI in Spring

AOP

1. What is AOP

AOP (Aspect Oriented Programming) means: Aspect Oriented Programming, which realizes the same maintenance of program functions through precompiled mode and runtime dynamic agent. AOP is the continuation of OOP, a hot spot in software development, an important content in Spring framework, and a derivative paradigm of functional programming. AOP can isolate each part of business logic, reduce the coupling between each part of business logic, improve the reusability of program, and improve the efficiency of development.

A O P of main want Merit can \Textcolor {orange} {main functions of AOP} Main functions of AOP

  • Logging
  • Performance statistics
  • safety control
  • transaction processing
  • Exception handling, etc

Spring AOP is simply understood as a knife, which can be inserted or pulled out at will during execution.

2. The role of AOP in Spring

Provide declarative transactions; Allows you to customize the cut plane

  • Crosscutting concerns: which write method to intercept and how to deal with it after interception have nothing to do with our business logic, but we need to focus on crosscutting concerns, such as logs, security, cache, transactions, etc. Methods or functions that span multiple modules of an application.
  • ASPECT: a special object whose crosscutting concerns are modularized, that is, it is a class
  • Advice: what aspect must do, that is, it is a method in a class
  • Target: the notified object, that is, the target object of the agent.
  • Proxy: an object created after notification is applied to the target object.
  • PointCut: the definition of the "place" where the aspect notification is executed
  • Join point: the execution point that matches the pointcut.
  • weave: the process of applying facets to the target object and causing the creation of proxy objects.

In spring AOP, crosscutting logic is defined through Advice. Spring supports five types of Advice

3. Using Spring to implement AOP

[key] to use AOP weaving, you need to import a dependency package

<dependencies>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.7</version>
    </dependency>
</dependencies>

Method 1: use Spring's api interface [mainly api interface]

UserService

package com.hxl.service;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void select();
}

UserServiceImpl

package com.hxl.service;

public class UserServiceImpl implements UserService{
    public void add() {
        System.out.println("Added a user");
    }

    public void delete() {
        System.out.println("A user was deleted");
    }

    public void update() {
        System.out.println("Modified a user");
    }

    public void select() {
        System.out.println("A user was queried");
    }
}

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: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
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--register bean-->
    <bean id="userService" class="com.hxl.service.UserServiceImpl"/>
    <bean id="log" class="com.hxl.log.Log"/>
    <bean id="afterLog" class="com.hxl.log.LogAfter"/>

    <!--Use native Spring API Interface-->
    <!--to configure aop:Import required aop Constraints of-->
    <aop:config>
        <!--breakthrough point;expression:expression,execution(Location to execute, modifier, return value, class name, method name, parameter)-->
        <aop:pointcut id="pointCut" expression="execution(* com.hxl.service.UserServiceImpl.*(..))"/>
        <!--Execute surround increase-->
        <aop:advisor advice-ref="log" pointcut-ref="pointCut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointCut"/>
    </aop:config>
</beans>

Test:

import com.hxl.service.UserService;
import com.hxl.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //Note: dynamic proxies are interfaces
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();
    }
}

Method 2: Customize to implement aop [mainly section]

DiyPointCut

package com.hxl.diy;

public class DiyPointCut {
    public void before(){
        System.out.println("====Before method execution====");
    }
    public void after(){
        System.out.println("====After method execution====");
    }
}
<!--Method 2: user defined class-->
<bean id="diy" class="com.hxl.diy.DiyPointCut"/>
<aop:config>
    <!--Custom cut, ref Class to reference-->
    <aop:aspect ref="diy">
        <!--breakthrough point-->
        <aop:pointcut id="point" expression="execution(* com.hxl.service.UserServiceImpl.*(..))"/>
        <!--notice-->
        <aop:before method="before" pointcut-ref="point"/>
        <aop:after method="after" pointcut-ref="point"/>
    </aop:aspect>
</aop:config>

Method 3: using annotations to implement aop

package com.hxl.diy;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

//Method 3: use annotation to implement aop
@Aspect//Label this class as a facet
public class AnnotationPointCut {
    @Before("execution(* com.hxl.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("====Before method execution====");
    }
    @After("execution(* com.hxl.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("====After method execution====");
    }
    //In surround enhancement, we can give a parameter representing the point where we want to get the processing pointcut
    @Around("execution(* com.hxl.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("====Surround front====");
        Signature signature = jp.getSignature();//Get signature
        System.out.println("signature:" + signature);
        //Execution method
        Object proceed = jp.proceed();
        System.out.println("=====After surround====");
    }
}
<!--Mode 3:-->
<bean id="annotationPointCut" class="com.hxl.diy.AnnotationPointCut"/>
<!--Enable annotation support
    JDK(default proxy-target-class="false")
    cglib(proxy-target-class="true")
    -->
<aop:aspectj-autoproxy />

proxy pattern

Why learn the proxy pattern? Because this is the bottom layer of spring AOP

During the interview, you will ask [spring AOP and apring MVC]

Agent mode is divided into static agent and dynamic agent

1. Static proxy

1.1 initial understanding

Role analysis:

  • Abstract role: it is usually solved by using interfaces or abstract classes
  • Real role: the role represented
  • Agent role: represents the real role. There are usually some ancillary operations after the agent
  • Customer: the person who accesses the proxy object!

Code steps

  1. Interface

    package com.hxl.demo01;
    
    //Rent a house
    public interface Rent {
        public void rent();
    
    }
    
  2. Real role

    package com.hxl.demo01;
    
    //landlord or landlady
    public class Host implements Rent{
    
        public void rent() {
            System.out.println("The landlord wants to rent the house");
        }
    }
    
  3. delegable role

    package com.hxl.demo01;
    
    public class Proxy implements Rent{
        private Host host;
    
        public Proxy() {
        }
    
        public Proxy(Host host) {
            this.host = host;
        }
    
        public void rent() {
            seeHouse();
            host.rent();
            contract();
            fare();
        }
        //House viewing
        public void seeHouse(){
            System.out.println("The agent will show you the house");
        }
        //sign a contract
        public void contract (){
            System.out.println("Sign a lease contract");
        }
        //Intermediary fee
        public void fare(){
            System.out.println("Intermediary fee");
        }
    }
    
  4. Client access agent role

    package com.hxl.demo01;
    
    public class Client {
        public static void main(String[] args) {
            Host host = new Host();
            //Agents and intermediaries rent houses for landlords. Generally, the agent role will have some ancillary operations
            Proxy proxy = new Proxy(host);
            //Do not face the landlord, directly find an intermediary to rent a house
            proxy.rent();
        }
    }
    

Benefits of agent mode:

  • It can make the operation of real roles more pure without paying attention to some public businesses
  • The public business is entrusted to the agent role to realize the division of business
  • When the public business is expanded, it is convenient for centralized management

Disadvantages of agent mode:

  • A real role produces a proxy role
  • The amount of code will double and the development efficiency will be low

1.2 re understanding

package com.hxl.demo02;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void query();
}
package com.hxl.demo02;

//Real object
public class UserServiceImpl implements UserService{
    public void add() {
        System.out.println("Added a user");
    }

    public void delete() {
        System.out.println("A user was deleted");
    }

    public void update() {
        System.out.println("Modified a user");
    }

    public void query() {
        System.out.println("A user was queried");
    }
}
package com.hxl.demo02;

public class UserServiceProxy implements UserService{
    private UserServiceImpl userService;

    public void setUserService(UserServiceImpl userService) {
        this.userService = userService;
    }

    public void add() {
        log("add");
        userService.add();
    }

    public void delete() {
        log("delete");
        userService.delete();
    }

    public void update() {
        log("update");
        userService.update();
    }

    public void query() {
        log("query");
        userService.query();
    }
    //Log method
    public void log(String msg){
        System.out.println("[Log output]Used" + msg + "method");
    }
}
package com.hxl.demo02;

public class Client {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        UserServiceProxy proxy = new UserServiceProxy();
        proxy.setUserService(userService);
        proxy.add();
    }
}

Using proxy will not change the structure of the original code, and many operations can be added in the proxy mode

A O P \textcolor{orange}{AOP} AOP

2. Dynamic agent

move state generation reason of bottom layer all yes back shoot \textcolor{orange} {the bottom layer of dynamic proxy is reflection} The bottom layer of dynamic proxy is reflection

  • Dynamic agents have the same role as static agents
  • The proxy class of dynamic proxy is generated dynamically, which is not written by us
  • Dynamic agents are divided into two categories: interface based dynamic agents and class based dynamic agents
    • Interface based - jdk dynamic agent
    • Class based cglib
    • java bytecode implementation: javassist
  • The dynamic proxy is the interface

Two classes need to be understood: Proxy: Proxy; InvocationHandler: call handler

InvocationHandler: under the reflection package (java.lang.reflect). It is an interface implemented by the calling handler of the proxy instance. Each proxy instance has an associated calling handler. When a method is called on the proxy instance, the method call will be encoded and dispatched to the invoke method of its calling handler

Benefits of dynamic agents:

  • It can make the operation of real roles more pure without paying attention to some public businesses
  • The public business is entrusted to the agent role to realize the division of business
  • When the public business is expanded, it is convenient for centralized management
  • A dynamic agent class represents an interface, which is generally a corresponding type of business
  • A dynamic proxy class can proxy multiple classes as long as it implements the same interface

2.1 initial understanding

Instead of writing a proxy role, let him generate it himself.

package com.hxl.demo03;

public class Host implements Rent{
    public void rent() {
        System.out.println("The landlord wants to rent a house");
    }
}
package com.hxl.demo03;

//Rent a house
public interface Rent {
    public void rent();
}

generation reason of class \textcolor{orange} {proxy class} Proxy class

package com.hxl.demo03;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//This class will be used to automatically generate proxy classes later
public class ProxyInvocationHandler implements InvocationHandler {
    //Proxy interface
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //Generated proxy class
    public Object getProxy(){
        Object o = Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
        return o;
    }

    //Process the proxy instance and return the result
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        //The essence of dynamic agent is to use reflection mechanism
        Object result = method.invoke(rent, args);
        fare();
        return result;
    }
    public void seeHouse(){
        System.out.println("The agent showed me the house");
    }
    public void fare(){
        System.out.println("Lease contract");
    }
}

measure try : \textcolor{orange} {test:} Test:

package com.hxl.demo03;

public class Client {
    public static void main(String[] args) {
        //Real role
        Host host = new Host();
        //Agent role: not now
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        //Handle the interface object we want to call by calling the program processing role
        pih.setRent(host);
        //Get proxy class
        Rent proxy = (Rent) pih.getProxy();//The proxy here is generated dynamically. We didn't write it
        proxy.rent();
    }
}

2.2 further understanding

We make it into a formula similar to. Make it live and intelligent

Agent:

package com.hxl.demo04;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//This class will be used to automatically generate proxy classes later
public class ProxyInvocationHandler implements InvocationHandler {
    //Proxy interface
    //Make it alive here
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    //Generated proxy class
    public Object getProxy(){
        Object o = Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        return o;
    }

    //Process the proxy instance and return the result
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //It can be written to death, such as log.add(); But it's not intelligent, so we have to enliven it
        log(method.getName());
        //The essence of dynamic agent is to use reflection mechanism
        Object result = method.invoke(target, args);
        return result;
    }

    public void log(String msg){
        System.out.println("Yes" + msg + "method");
    }
}

Test:

package com.hxl.demo04;

import com.hxl.demo02.UserService;
import com.hxl.demo02.UserServiceImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class Client {
    public static void main(String[] args) {
        //Real role
        UserServiceImpl userService = new UserServiceImpl();
        //Agent role. non-existent
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        //Sets the object to proxy
        pih.setTarget(userService);
        //Dynamically generate proxy classes
        UserService proxy = (UserService) pih.getProxy();
        proxy.add();
    }
}

Keywords: Java Spring Back-end SSM

Added by yuws on Sun, 21 Nov 2021 01:05:32 +0200