设为首页 加入收藏

TOP

day09-AOP-02(一)
2023-07-25 21:42:59 】 浏览:57
Tags:day09-AOP-02

AOP-02

4.问题提出

在上一篇的MyProxyProvider类中,我们的输出语句功能比较弱,在实际开发中,我们希望是以一个方法的形式,嵌入到真正执行的目标方法前,怎么办?

image-20230123225502663

1.使用土方法解决

需求分析:使用土方法解决前面的问题,后面使用spring的aop组件完成

改进MyProxyProvider:

主要是对前置/返回/异常/最终通知的代码进行封装,封装到不同的方法中进行调用。

package com.li.aop.proxy3;

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

/**
 * @author 李
 * @version 1.0
 * 返回一个动态代理对象,可以执行被代理的对象的方法
 */
public class MyProxyProvider {

    //定义要执行的目标对象,该对象需要实现 SmartAnimal接口
    private SmartAnimal target_animal;

    //构造器
    public MyProxyProvider(SmartAnimal target_animal) {
        this.target_animal = target_animal;
    }

    //定义一个方法,在目标对象执行前执行
    public void before(Method method, Object[] args) {
        System.out.println("before-方法执行开始-日志-方法名-" + method.getName() +
                "-参数 " + Arrays.toString(args));//AOP的角度看,是一个横切关注点-前置通知
    }

    //定义一个方法,在目标对象执行后行
    public void after(Method method, Object result) {
        System.out.println("after-方法执行正常结束-日志-方法名-" + method.getName()
                + "-结果 result = " + result);//也是一个横切关注点-返回通知
    }

    //定义方法返回代理对象,该代理对象可以执行目标对象
    public SmartAnimal getProxy() {
        //(1)先得到类加载器对象
        ClassLoader classLoader = target_animal.getClass().getClassLoader();
        //(2)得到要执行的目标对象的接口信息
        Class<?>[] interfaces = target_animal.getClass().getInterfaces();
        //(3)使用匿名内部类 创建 InvocationHandler对象
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object result = null;
                try {

                    before(method, args);

                    //使用反射真正调用方法
                    result = method.invoke(target_animal, args);

                    after(method, result);

                } catch (Exception e) {
                    //如果反射出现异常,就会进入到catch块
                    System.out.println("方法执行异常-日志-方法名" + method.getName()
                            + "-异常类型=" + e.getClass().getName());//横切关注点-异常通知
                    e.printStackTrace();
                } finally {//无论是否出现异常,最终都会执行到 finally{}
                    //也是一个横切关注点-最终通知
                    System.out.println("方法最终结束-日志-方法名-" + method.getName());
                }
                return result;
            }
        };

        //创建代理对象
        SmartAnimal proxy = (SmartAnimal) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
        return proxy;
    }
}

2.对土方法进行解耦-开发简易的AOP类

上面的代码因为前后置等处理方法都写在同一个类中,造成代码耦合度高的问题。因此,更好的解决方法是新建一个类MyAOP,在该类中进行处理方法的编写,然后在MyProxyProvider类中调用该类的方法。

MyAOP类:

package com.li.aop.proxy3;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @author 李
 * @version 1.0
 * 自己写的一个极简AOP类
 */
public class MyAOP {
    //定义一个方法,在目标对象执行前执行
    public static void before(Method method, Object[] args) {
        System.out.println("MyAOP-方法执行开始-日志-方法名-" + method.getName() +
                "-参数 " + Arrays.toString(args));//前置通知
    }

    //定义一个方法,在目标对象执行后行
    public static void after(Method method, Object result) {
        System.out.println("MyAOP-方法执行正常结束-日志-方法名-" + method.getName()
                + "-结果 result = " + result);//返回通知
    }

}

3.再次分析-提出Spring AOP

使用上面的办法仍存在一些问题:

  1. 不够灵活:假设被代理对象有很多方法,而我们只想仅对其中一个方法进行处理,当前的代码还不能实现这个需求
  2. 复用性差:假如有一个新的接口USBInterface,Phone类实现了这个接口,现在我们想要Phone类去调用之前MyAOP中的方法。但MyAOP类的方法是根据之前的SmartAnimal接口的方法写的,因此不能很好的适用于新的接口及其实现类
  3. 硬编码:没有注解和反射的支撑

5.AOP的基本介绍

1.什么是AOP?

官方文档:核心技术 (spring.io)

AOP全称:aspect oriented programming,即面向切面编程。

AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面。

2.A

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇读Java8函数式编程笔记01_Lambda.. 下一篇LeetCode-343. 整数拆分 - 题解分..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目