JAVA高级应用—— AOP(动态代理)

什么是AOP?

简单理解:方法增强。

		AOP是一种编程范式,与语言无关,是一种程序设计思想。
		面向切面编程(AOP)Aspect Oriented Programming。
		切面编程的目的是为了把通用逻辑从业务逻辑分离出来。

AOP可以增强方法的功能,而不需要修改原业务代码。

深入理解

从编程语言的角度:处理粒度不同
AOP是对OOP的扩展,OOP(即面向对象编程)能处理的最大粒度是对象,对OOP而言,当需要增强方法的功能时,必须修改类的定义。而AOP能处理的粒度可以深入到对象内部,可以是方法或者字段(Spring暂不支持字段增强),所以AOP可以使我们不用重新定义类,而增强原方法。
从设计模式的角度:AOP进一步降低了模块间的耦合度
使得业务代码和功能性代码分离,降低它们之间的耦合度。

功能性代码,如:事务处理、参数校验、日志、监控、负载均衡

从解放程序员生产力的角度:更少的代码
AOP只需要少量的配置或者注解就可以完成
从代码可读性的角度:业务逻辑更清晰
程序员可以更聚焦于业务逻辑。

AOP的核心是什么?

动态代理

AOP主要是做什么?(动态代理做什么?)

对那些被代理对象的那些方法在方法运行到那些时段做什么增强。

JDK动态代理

JDK动态代理不需要重写实现类,也不需要定义一个实现UserService接口的代理类。而是使用Proxy类帮我们动态生成代理类。

package day05.Agent2;

import day05.Agent.UserService;

import java.lang.reflect.Proxy;
import java.text.SimpleDateFormat;
import java.util.Date;
    //jdk
   public class UserServiceProxy {
        private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 返回动态代理对象
     * @param userService 被代理对象
     * @return 代理对象
     */
    public static UserService newProxyInstance(UserService userService) {
            /*
             * Proxy.newProxyInstance方法返回动态生成的代理类
             * 参数:
             *  userService.getClass().getClassLoader():被代理类的类加载器;
             *  userService.getClass().getInterfaces():被代理类的接口,重要!说明JDK动态代理是基于代理接口的。
             *  第三个参数定义了一个内部类,实现了代理逻辑,内部参数:
             *      o:代理类对象;
             *      method:被代理方法;
             *      objects:被代理方法的参数;
             */
            return (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
                    userService.getClass().getInterfaces(), (o, method, objects) -> {
                        // 调用被代理方法
                        Object ret = method.invoke(userService, objects);
                        // 编写增强功能
                        System.out.println(dateFormat.format(new Date()) + ": method " + method.getName() + " invoked");
                        return ret;
                    });
        }
}


test:

package day05;

import day05.Agent.UserService;
import day05.Agent.UserServiceImpl;
import day05.Agent2.Impl;

public class client {
    public static void main(String[] args) {
        System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        UserService userService = Impl.newInstance(new UserServiceImpl());
        userService.getUser();
        userService.createUser();
        userService.updateUser();
        userService.deleteUser();
    }
}

Cglib动态代理

public class UserServiceCglibProxy {

    private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 返回动态代理对象
     * @param userService 被代理对象
     * @return 代理对象
     */
    public static UserService newProxyInstance(UserService userService) {

        /*
         * Enhancer.create方法返回动态生成的代理类
         * 参数:
         *  userService.getClass():被代理类的类;
         *  第二个参数定义了一个内部类,实现了代理逻辑,内部参数:
         *      o:代理类对象;
         *      method:被代理方法;
         *      objects:被代理方法的参数;
         *      methodProxy:方法代理;
         */
        return (UserService) Enhancer.create(userService.getClass(), (MethodInterceptor) (o, method, objects, methodProxy) -> {
            // 调用被代理方法
            Object ret = methodProxy.invokeSuper(o, objects);
            // 编写增强功能
            System.out.println(dateFormat.format(new Date()) + ": method " + method.getName() + " invoked");
            return ret;
        });
    }
}

test:

   public static void main(String[] args) {
        // 保存动态生成的代理类的字节码
//        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "C:\\code");
        UserService userService = UserServiceCglibProxy.newProxyInstance(new UserServiceImpl());
        userService.getUser();
        userService.createUser();
        userService.updateUser();
        userService.deleteUser();
    }

二者区别

简单理解

使用场景

JDK动态代理用于接口
例如,我们要代理UserServiceImpl,则UserServiceImpl必须实现一个接口,例如UserService接口;
Cglib用于类或者接口
例如,我们要代理UserServiceImpl,不需要关注该类是否实现接口。

效率

Java8之前,Cglib效率高;
Java8开始,JDK动态代理效率高;
深入理解

为什么JDK动态代理必须要有接口,而Cglib则不需要

这是由他们的实现方式决定的。
JDK动态代理生成类继承关系

表达式详解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值