手撕Spring5框架(五)AOP介绍

基本概念

AOP,面向切面编程,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

主要意图

将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

核心思想:不通过修改源代码方式添加新功能。

实际案例分享:

例如我们现在有一个用户登录的功能,现在需要增加一个新的功能,就是登录完成后增加登录信息的记录的功能,记录的信息包括登录名称、登录时间、登录的ip地址、登录的操作系统等内容。我们会有两种方式实现,一种是修改源代码,在登录功能代码中添加记录用户登录信息功能,另外一种方式是通过AOP的方式不改变源代码添加登录信息记录的功能。

AOP实现方式如下图:

AOP的底层实现原理

AOP底层使用动态代理实现:

动态代理实现有两种方式

1)被代理的对象有接口情况

使用JDK动态代理实现

场景:

2)被代理的对象没有接口的情况

使用CGLIB动态代理实现

场景:

AOP(JDK动态代理)实现原理

编写JDK动态代理代码:

1)创建接口UserDao和接口实现类UserDaoImpl

package org.learn.spring5.dao;

public interface UserDao {
    int add();

    int update(Integer id);

}
package org.learn.spring5.dao.impl;

import org.learn.spring5.dao.UserDao;

/**
 * UserDao的实现类
 */
public class UserDaoImpl implements UserDao {


    public int add() {
        System.out.println("UserDaoImpl add ");
        return 1;
    }

    public int update(Integer id) {

        System.out.println("UserDaoImpl  update");
        return id;
    }
}

2)创建MyInvocationHandler类实现InvocationHandler,该类用于实现代理类调用的方法增强的那部

分的处理。增强处理的内容是在invoke方法中,在代理类调用方法时,执行invoke方法。

package org.learn.spring5.dao.impl;

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

//创建代理对象调用的程序代码
public class MyInvocationHandler implements InvocationHandler {
    private Object object;
    //有参构造传递
    public MyInvocationHandler(Object object){
        this.object = object;
    }

    //增强的逻辑
    //第一个参数:类加载
    //第二个参数:增强方法所在的类,这个类实现的接口,支持多个接口
	//第三个参数:实现这个接口InvocationHandler,创建代理对象,写增强的方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("方法之前处理");

        //被增强的方法执行
        Object invoke = method.invoke(object,args);

        System.out.println("方法之后处理");


        return invoke;
    }
}

3)利用Proxy类生成代理对象的实例,调用相应的被代理类的方法。

import org.learn.spring5.dao.UserDao;
import org.learn.spring5.dao.impl.MyInvocationHandler;
import org.learn.spring5.dao.impl.UserDaoImpl;

import java.lang.reflect.Proxy;

class TestProxy {

    public static void main(String[] args) {
        //被增强的类,真实的角色
        UserDaoImpl userDaoImpl = new UserDaoImpl();
        Class[] interfaces = {UserDao.class};  //接口
        //动态生成代理对象的实例并返回,传递谁就生产谁的代理对象
        UserDao dao = (UserDao) Proxy.newProxyInstance(TestProxy.class.getClassLoader(),             	userDaoImpl.getClass().getInterfaces(), new MyInvocationHandler(userDaoImpl));
        int res = dao.update(1);
        System.out.println(res);
    }
}

AOP操作术语

  • 连接点

    类里面哪些方法可以被增强,这些方法就被称为连接点。

  • 切入点

    实际被增强的方法,称之为切入点

  • 通知(增强)

    实际增强的内容被称为通知

    通知有多种类型:

    前置通知

    后置通知

    环绕通知

    异常通知

    最终通知

  • 切面

    通知应用到切入点的过程

  • 切入点表达式

    (1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强

    (2)语法结构:

    excution (<权限修饰符><返回类型><类全路径><方法名称>(<参数列表>))

    (3)示例:对org.learn.spring5.UserDao类的add方法进行增强

    excution(* org.learn.spring5.UserDao.add(..))

    示例:对org.learn.spring5.UserDao类的所有方法进行增强

    excution(* org.learn.spring5.UserDao.*(..))

猜你喜欢

转载自blog.csdn.net/java_cxrs/article/details/108353167