• 手动实现SPring中的AOP(2)


    相关名词的解释:通知定义了要织入目标对象的逻辑,以及执行时机。
    Spring 中对应了 5 种不同类型的通知:
    · 前置通知(Before):在目标方法执行前,执行通知
    · 后置通知(After):在目标方法执行后,执行通知,此时不关系目标方法返回的结果是什么
    · 返回通知(After-returning):在目标方法执行后,执行通知
    · 异常通知(After-throwing):在目标方法抛出异常后执行通知
    · 环绕通知(Around): 目标方法被通知包裹,通知在目标方法执行前和执行后都被会调用

    切点(Pointcut):如果说通知定义了在何时执行通知,那么切点就定义了在何处执行通知。所以切点的作用就是通过匹配规则查找合适的连接点(Joinpoint),AOP 会在这些连接点上织入通知。

     切面(Aspect):切面包含了通知和切点,通知和切点共同定义了切面是什么,在何时,何处执行切面逻辑。

    实现步骤:

    1. 定义一个包含切面逻辑的对象,这里假设叫 logMethodInvocation
    2. 定义一个 Advice 对象(实现了 InvocationHandler 接口),并将上面的 logMethodInvocation 和 目标对象传入
    3. 将上面的 Adivce 对象和目标对象传给 JDK 动态代理方法,为目标对象生成代理
    
    
    MethodInvocation 接口  // 实现类包含了切面逻辑,如上面的 logMethodInvocation
    Advice 接口        // 继承了 InvocationHandler 接口
    BeforeAdvice 类    // 实现了 Advice 接口,是一个前置通知
    SimpleAOP 类       // 生成代理类
    SimpleAOPTest      // SimpleAOP 从测试类
    HelloService 接口   // 目标对象接口
    HelloServiceImpl   // 目标对象
    
    
    

    MethodInvocation 接口代码:

    public interface MethodInvocation {
        void invoke();
    }

     Advice 接口代码:

    public interface Advice extends InvocationHandler {}

    BeforeAdvice 实现代码:

    public class BeforeAdvice implements Advice {
        private Object bean;
        private MethodInvocation methodInvocation;
    
        public BeforeAdvice(Object bean, MethodInvocation methodInvocation) {
            this.bean = bean;
            this.methodInvocation = methodInvocation;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 在目标方法执行前调用通知
            methodInvocation.invoke();
            return method.invoke(bean, args);
        }
    }

    SimpleAOP 实现代码:

    public class SimpleAOP {
        public static Object getProxy(Object bean, Advice advice) {
            return Proxy.newProxyInstance(SimpleAOP.class.getClassLoader(), 
                    bean.getClass().getInterfaces(), advice);
        }
    }

    HelloService 接口,及其实现类代码:

    public interface HelloService {
        void sayHelloWorld();
    }
    
    public class HelloServiceImpl implements HelloService {
        @Override
        public void sayHelloWorld() {
            System.out.println("hello world!");
        }
    }

    SimpleAOPTest 代码:

    
    
    public class SimpleAOPTest {
        @Test
        public void getProxy() throws Exception {
            // 1. 创建一个 MethodInvocation 实现类
            MethodInvocation logTask = () -> System.out.println("log task start");
            HelloServiceImpl helloServiceImpl = new HelloServiceImpl();
            
            // 2. 创建一个 Advice
            Advice beforeAdvice = new BeforeAdvice(helloServiceImpl, logTask);
            
            // 3. 为目标对象生成代理
            HelloService helloServiceImplProxy = (HelloService) SimpleAOP.getProxy(helloServiceImpl,beforeAdvice);
            
            helloServiceImplProxy.sayHelloWorld();
        }
    }
    
    
    

      

     
  • 相关阅读:
    Python eval 函数妙用
    502与504故障分析与解决方法
    [转]谈谈select, iocp, epoll,kqueue及各种网络I/O复用机制
    计算阶乘n!末尾0的个数
    C++中的Overload、Override和Overwrite
    C++中的空类与空结构体大小
    多线程编程之优先级翻转问题
    数据库原理之事务(二)
    数据库原理之事务(一)
    NoSQL之基础篇
  • 原文地址:https://www.cnblogs.com/BaoZiY/p/11375859.html
Copyright © 2020-2023  润新知