Spring Framework-Aspect Oriented (AOP)

1. Agency model

1.1 What is the proxy mode

In the Proxy Pattern, one class represents the function of another class. This type of design pattern is a structural pattern.

In the proxy mode, we create objects with existing objects in order to provide functional interfaces to the outside world.
The main solution : the problems caused by direct access to the object, for example: the object to be accessed is on a remote machine. In an object-oriented system, for some reasons (for example, object creation is expensive, or certain operations require security control, or need out-of-process access), direct access will bring a lot of trouble to the user or the system structure. We can add

advantage:

  • 1. Clear responsibilities.
  • 2. High scalability.
  • 3. Intelligent.

Disadvantages:

  • 1. Due to the addition of proxy objects between the client and the real subject, some types of proxy modes may slow down the processing speed of the request.
  • 2. The implementation of the proxy mode requires additional work, and the implementation of some proxy modes is very complicated.
1.2 Static proxy

Create an interface

//定义接口 增删改查方法
public interface UserService {
    
    
    public void insert();
    public void delete();
    public void update();
    public void select();
}

Create an implementation class that implements the interface

public class UserServiceImpl implements UserService {
    
    
    public void insert() {
    
    
        System.out.println("实现了增加的功能!");
    }

    public void delete() {
    
    
        System.out.println("实现了删除的功能!");
    }

    public void update() {
    
    
        System.out.println("实现了修改的功能!");
    }

    public void select() {
    
    
        System.out.println("实现了查询的功能!");
    }
}

Proxy class

public class UserServiceProxy implements UserService {
    
    
    //如果我想要实现扩展的业务功能
    private UserServiceImpl userServiceImpl;

    public UserServiceProxy() {
    
    
    }

    public void setUserServiceImpl(UserServiceImpl userServiceImpl) {
    
    
        this.userServiceImpl = userServiceImpl;
    }

    public void insert() {
    
    
        log("insert");
        System.out.println("实现了增加的功能!");
    }

    public void delete() {
    
    
        log("delete");
        System.out.println("实现了删除的功能!");
    }

    public void update() {
    
    
        log("update");
        System.out.println("实现了修改的功能!");
    }

    public void select() {
    
    
        log("select");
        System.out.println("实现了查询的功能!");
    }

    //日志方法
    public void log(String msg){
    
    
        System.out.println("[Debug] 使用了"+msg+"方法");
    }
}

test

public class Client {
    
    
    public static void main(String[] args) {
    
    
        UserServiceImpl userService = new UserServiceImpl();
        UserServiceProxy userProxy = new UserServiceProxy();
        userProxy.setUserServiceImpl(userService);
        userProxy.insert();
        userProxy.delete();
        userProxy.update();
        userProxy.select();
}
1.3 Dynamic proxy

Create an interface

//定义接口 增删改查方法
public interface UserService {
    
    
    public void insert();
    public void delete();
    public void update();
    public void select();
}

Create an implementation class that implements the interface

public class UserServiceImpl implements UserService {
    
    
    public void insert() {
    
    
        System.out.println("实现了增加的功能!");
    }

    public void delete() {
    
    
        System.out.println("实现了删除的功能!");
    }

    public void update() {
    
    
        System.out.println("实现了修改的功能!");
    }

    public void select() {
    
    
        System.out.println("实现了查询的功能!");
    }
}

Automatic generation of proxy classes

//自动生成代理类!
public class ProxyInvocationHandler implements InvocationHandler {
    
    
    //被代理的接口
    private Object target;

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

    //生成得到代理类
    public Object getProxy(){
    
    
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    //处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        log(method.getName());
        Object result = method.invoke(target, args);
        return result;
    }
    public void log(String msg){
    
    
        System.out.println("[Debug] 使用了"+msg+"方法");
    }
}

test

public class Client {
    
    
    public static void main(String[] args) {
    
    
        //真实角色
        UserServiceImpl userService = new UserServiceImpl();
        //代理角色
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        //设置代理的对象
        pih.setTarget(userService);
        //动态生成代理类
        UserService proxy = (UserService) pih.getProxy();
        proxy.select();
    }
}

result
Insert picture description here

2. Aspect-oriented (AOP)

2.1 What is AOP

AOP (Aspect Oriented Programming) means: Aspect Oriented Programming, a technology that achieves unified maintenance of program functions through pre-compilation and runtime dynamic agents. AOP is a continuation of OOP, a hot spot in software development, and an important content in the Spring framework, and a derivative paradigm of functional programming. The use of AOP can isolate various parts of the business logic, thereby reducing the coupling between the various parts of the business logic, improving the reusability of the program, and improving the efficiency of development at the same time.

Insert picture description here

2.2 The role of Aop in Spring

提供声明式事务;允许用户自定义切面

  • Cross-cutting concerns: methods or functions that span multiple modules of an application. That is, it has nothing to do with our business logic, but the part we need to focus on is the cross-cutting focus. Such as log, security, cache, transaction, etc...
  • ASPECT: A special object whose cross-cutting concerns are modularized. That is, it is a class.
  • Advice: The work that the aspect must complete. That is, it is a method in the class.
  • Target: The notified object.
  • Proxy: The object created after applying the notification to the target object.
  • PointCut: The definition of the "location" of the point cut notification execution.
  • Joint Point: The execution point
    Insert picture description here
    that matches the entry point . In Spring
    Insert picture description here
    AOP , crosscutting logic is defined through Advice. Spring supports 5 types of Advice: Aop adds new functions without changing the original code.
2.3 Spring implements Aop

Use Aop needs to import dependencies

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>
2.3.1 Use Spring's API interface

Create interface

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

Create an implementation class that implements the interface

public class UserServiceImpl implements UserService {
    
    
    public void insert() {
    
    
        System.out.println("实现了增加的功能!");
    }

    public void delete() {
    
    
        System.out.println("实现了删除的功能!");
    }

    public void update() {
    
    
        System.out.println("实现了修改的功能!");
    }

    public void select() {
    
    
        System.out.println("实现了查询的功能!");
    }
}

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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
        
    <!-- 注册bean -->
    <bean id="userService" class="com.li.service.UserServiceImpl"/>
    <bean id="log" class="com.li.log.Log"/>
    <bean id="afterLog" class="com.li.log.AfterLog"/>

    <!-- 配置aop:需要导入aop的约束-->
   <aop:config>
       <!-- 切入点:expression 表达式,execution(要执行的位置! * * * * *)-->
       <aop:pointcut id="pointcut" expression="execution(* com.li.service.UserServiceImpl.*(..))"/>
       <!-- 执行环绕增加! -->
       <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
       <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
   </aop:config>
</beans>

test

public class MyTest {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) context.getBean("userService");
        userService.insert();
    }
}
2.3.2 Customize to achieve AOP [mainly aspect definition]

Interface as interface class.
Front, Rear class

public class DiyPointCut {
    
    
    public void before(){
    
    
        System.out.println("===========方法执行前===========");
    }
    public void after(){
    
    
        System.out.println("===========方法执行后===========");
    }
}

    <!-- 注册bean -->
    <bean id="userService" class="com.li.service.UserServiceImpl"/>
    <bean id="log" class="com.li.log.Log"/>
    <bean id="afterLog" class="com.li.log.AfterLog"/>

  方式二:自定义类
    <bean id="diy" class="com.li.diy.DiyPointCut"/>

    <aop:config>
        <!-- 自定义切面 ,ref 要引用的类-->
        <aop:aspect ref="diy">
            <!-- 切入点 -->
            <aop:pointcut id="point" expression="execution(* com.li.service.UserServiceImpl.*(..))"/>
            <!-- 通知 -->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
   
2.3.3 Implementation using annotations

Configuration file

  <!-- 方式三-->
    <bean id="annotationPointCut" class="com.li.diy.AnnotationPointCut"/>
    <!-- 开启注解支持 -->
    <aop:aspectj-autoproxy/>
    <!-- 注册bean -->
    <bean id="userService" class="com.li.service.UserServiceImpl"/>
    <bean id="log" class="com.li.log.Log"/>
    <bean id="afterLog" class="com.li.log.AfterLog"/>

Noodles

@Aspect//标注这个类是一个切面
public class AnnotationPointCut {
    
    
    @Before("execution(* com.li.service.UserServiceImpl.*(..))")
    public void before(){
    
    
        System.out.println("====方法执行前====");
    }

    @After("execution(* com.li.service.UserServiceImpl.*(..))")
    public void after(){
    
    
        System.out.println("====方法执行后====");
    }
    //在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
    @Around("execution(* com.li.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
    
    
        System.out.println("环绕前");
        Object proceed = jp.proceed();//执行方法
        System.out.println("环绕后");
    }

Guess you like

Origin blog.csdn.net/lirui1212/article/details/106468247