Spring中如何通过JDK动态代理实现AOP

267 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天

JDK动态代理

默认情况下,Spring AOP使用JDK动态代理,JDK动态代理是通过java.lang.reflect.Proxy类实现的,可以调用Proxy类的newProxyInstance()方法创建代理对象。JDK动态代理可以实现无侵入式的代码扩展,并且可以在不修改源代码的情况下,增强某些方法。

实现过程演示:

第一步:

在IDEA中创建Maven项目,然后在其pom.xml文件中加载需要用到的Spring基础包和Spring依赖包(4+1)。

第二步:

创建接口UserDao,在UserDao接口中编写添加和删除的方法。

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

第三步:

创建UserDao接口的实现类UserDaoImpl,分别实现接口中的方法。

public class UserDaoImpl implements UserDao{
    public void addUser(){
        System.out.println("添加用户");
    }
    public void deleteUser(){
        System.out.println("删除用户");
    }
}

第四步:

创建切面类MyAspect,该类中定义一个模拟权限检查的方法和一个模拟日志记录的方法,这两个方法就是切面中的通知。

//切面类:存在多个通知Advice(增强的方法)
public class MyAspect{
    public void check_permissions(){
        //权限检查
    }
    public void log(){
        //记录日志
    }
}

第五步:

创建代理类Myproxy,该类需要实现InvocationHandler接口设置代理类的调用处理程序。在代理类中,通过newProxyInstance()生成代理方法

public class MyProxy implements InvocationHandler{
    private UserDao userDao;
    public Object createProxy(UserDao userDao){
        this.userDao = userDao;
        ClassLoader classLoader = MyProxy.class.getClassLoader();//类加载器
        Class[] classes = userDao.getClass().getInterfaces();//被代理对象实现的所有接口
        return Proxy.newProxyInstance(classLoader, classes, this);//返回代理对象
    }
    /*
    * 所有动态代理类的方法调用,都会交由invoke()方法去处理
    * proxy 被代理的对象
    * method 将要被执行的方法信息(反射)
    * args 执行方法时所需要的参数
    */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
        //创建切面对象
        MyAspect myAspect = new MyAspect();
        //前增强:权限检查
        myAspect.check_Permissions();
        //在目标类上调用方法,并传入参数,执行目标方法
        Object obj = method.invoke(userDao, args);
        //后增强:日志记录
        myAspect.log();
        return obj;
    }
}

第六步: 测试

public class JDKTest{
    public static void main(String[] args){
        MyProxy jdkProxy = new Myproxy();
        UserDaoImpl userDao = new UserDaoImpl();
        //创建代理对象
        UserDao userDao1 = (UserDao) jdkProxy.createProxy(UserDao);
        //通过代理对象调用方法
        userDao1.addUser();
        userDao1.deleteUser();
    }
}