手动实现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();
    }
}
 

  

 

猜你喜欢

转载自www.cnblogs.com/BaoZiY/p/11375859.html