从零开始造Spring08---AOP(介绍以及实现ReflectiveMethodInvocation和AopProxyFactory)

简介: 这是学习刘老师的《从零开始造Spring》的学习笔记,接上篇笔记从零开始造Spring07

前言


这是学习刘老师的《从零开始造Spring》的学习笔记,接上篇笔记从零开始造Spring07


如何实现指定次序的链式调用

SpringAOP定义的拦截器

80452a3e0ae49cdc82c299ca18c24d32_70.png


从类图中我们可以看出Advice 接口继承了来自AOP Aliance 中的MethodInterceptor 类。该类中的invoke 方法通过传入Methodinvocation 对象,而Methodinvocation的proceed方法则是实现链式调用的关键。


ReflectiveMethodInvocation类实现了Methodinvocation 接口

4d1875cf5b0107b48d6e4709e7da45c5_70.png

如图我们可以看到ReflectiveMethodInvocation类的构造器中有3个参数,第一个参数是 待拦截的对象,第二个为 待拦截的方法,第三个为 拦截器列表。


关键代码实现

ReflectiveMethodInvocation 中的proceed方法

@Override
    public Object proceed() throws Throwable {
        //所有拦截器调用完成
        if (this.currentInterceptorIndex == this.interceptors.size() - 1) {
            return invokeJoinpoint();
        }
        //currentInterceptorIndex初始值为-1
        this.currentInterceptorIndex++;
        MethodInterceptor interceptor = this.interceptors.get(this.currentInterceptorIndex);
        return interceptor.invoke(this);
    }


首先会检查传入的拦截器是否调用完成,如果调用完成则返回,否则,则先调用当前拦截器的invoke 方法。

AspectJBeforeAdvice 类的invoke方法

@Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
//        例如:调用TransactionManager的start方法
        this.invokeAdviceMethod();
        Object proceed = methodInvocation.proceed();
        return proceed;
    }


AspectJAfterReturningAdvice 类的invoke方法

@Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        Object proceed = methodInvocation.proceed();
//        例如:调用TransactionManager的commit方法
        this.invokeAdviceMethod();
        return proceed;
    }


比较AspectJBeforeAdvice 类和AspectJAfterReturningAdvice类的invoke方法,我们发现一个明显的区别是invokeAdviceMethod 方法调用顺序,在AspectJBeforeAdvice中首先会调用自身的拦截方法之后才会调用其他的拦截器。在AspectJAfterReturningAdvice中必须等其他的拦截器调用完毕才会调用自身的拦截方法。这就实现了指定次序的链式调用。


相关测试代码

@Test
    public void testMethodInvocation1() throws Throwable {
        Method targetMethod = PetStoreService.class.getMethod("placeOrder");
        List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>();
        interceptors.add(afterAdvice);
        interceptors.add(beforeAdvice);
        ReflectiveMethodInvocation mi = new ReflectiveMethodInvocation(petStoreService, targetMethod, new Object[0], interceptors);
        mi.proceed();
        List<String> msgs = MessageTracker.getMsgs();
        Assert.assertEquals(3, msgs.size());
        Assert.assertEquals("start tx", msgs.get(0));
        Assert.assertEquals("place order", msgs.get(1));
        Assert.assertEquals("commit tx", msgs.get(2));
    }


通过Factory 获得代理实例

Cglib 动态代理

Cglib动态代理是通过扩展子类来实现对父类的增强。

@Test
    public void testCallBack() {
        // Cglib的增强者
        Enhancer enhancer = new Enhancer();
//        设置父类
        enhancer.setSuperclass(PetStoreService.class);
        enhancer.setCallback(new TransactionInterceptor());
//        创建代理
        PetStoreService petStoreService = (PetStoreService) enhancer.create();
        petStoreService.placeOrder();
    }
    //Cglib定义的拦截器
    public static class TransactionInterceptor implements MethodInterceptor {
        TransactionManager txManager = new TransactionManager();
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            txManager.start();
            Object result = proxy.invokeSuper(obj, args);
            txManager.commit();
            return result;
        }
    }


通过Factory 获得代理实例

首先我们看一下类图

f0cc5bde4753ec8ddf3b91b7d7c915b5_70.png

如类图所示

关键代码:

public class CglibProxyFactory implements AopProxyFactory {
   //在某种情况下选择对应的拦截器
    private static final int AOP_PROXY = 0;
    private static final int INVOKE_TARGET = 1;
    private static final int NO_OVERRIDE = 2;
    private static final int DISPATCH_TARGET = 3;
    private static final int DISPATCH_ADVISED = 4;
    private static final int INVOKE_EQUALS = 5;
    private static final int INVOKE_HASHCODE = 6;
    protected static final Log logger = LogFactory.getLog(CglibProxyFactory.class);
    protected final AopConfig config;
    private Object[] constructorArgs;
    private Class<?>[] constructorArgTypes;
    public CglibProxyFactory(AopConfig config) throws AopConfigException {
        Assert.notNull(config, "AdvisedSupport must not be null");
        if (config.getAdvices().size() == 0 /*&& config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE*/) {
            throw new AopConfigException("No advisors and no TargetSource specified");
        }
        this.config = config;
    }
  @Override
    public Object getProxy() {
         return getProxy(null);
    }
    //创建代理的方法
    @Override
    public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating CGLIB proxy: target source is " + this.config.getTargetClass());
        }
        //拿到class对象
        Class<?> rootClass = this.config.getTargetClass();
        //实例化增强器
        Enhancer enhancer = new Enhancer();
        if (classLoader != null) {
            enhancer.setClassLoader(classLoader);
        }
        enhancer.setSuperclass(rootClass);
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);//"BySpringCGLIB"
        enhancer.setInterceptDuringConstruction(false);
        Callback[] callbacks = getCallbacks(rootClass);
        Class<?>[] types = new Class<?>[callbacks.length];
        for (int i = 0; i < types.length; i++) {
            types[i] = callbacks[i].getClass();
        }
        enhancer.setCallbackFilter(new ProxyCallbackFilter(this.config));
        enhancer.setCallbackTypes(types);
        enhancer.setCallbacks(callbacks);
        Object proxy = enhancer.create();
        return proxy;
    }
    private Callback[] getCallbacks(Class<?> rooClass) {
    //创建Callback
        Callback aopInterceptor = new DynamicAdvisedInterceptor(this.config);
        Callback[] callbacks = new Callback[] {
                aopInterceptor,  // AOP_PROXY for normal advice
                /*targetInterceptor,  // INVOKE_TARGET invoke target without considering advice, if optimized
                new SerializableNoOp(),  // NO_OVERRIDE  no override for methods mapped to this
                targetDispatcher,        //DISPATCH_TARGET
                this.advisedDispatcher,  //DISPATCH_ADVISED
                new EqualsInterceptor(this.advised),
                new HashCodeInterceptor(this.advised)*/
        };
        return callbacks;
    }
    private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
        private final AopConfig config;
        public DynamicAdvisedInterceptor(AopConfig advised) {
            this.config = advised;
        }
        //
        @Override
        public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            //获取targetObject
            Object target = this.config.getTargetObject();
            //获取advices列表
            List<Advice> chain = this.config.getAdvices(method);
            Object retVal;
            //列表为空,啥都不干
            if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                retVal = methodProxy.invoke(target, args);
            } else {
            //生成拦截器列表
                List<org.aopalliance.intercept.MethodInterceptor> interceptors =
                        new ArrayList<org.aopalliance.intercept.MethodInterceptor>();
                interceptors.addAll(chain);
                // We need to create a method invocation...
                retVal = new ReflectiveMethodInvocation(target, method, args, interceptors).proceed();
            }
            return retVal;
        }
    }
    /**
     * CallbackFilter to assign Callbacks to methods.
     */
    private static class ProxyCallbackFilter implements CallbackFilter {
        private final AopConfig config;
        public ProxyCallbackFilter(AopConfig advised) {
            this.config = advised;
        }
        public int accept(Method method) {
            // 注意,这里做了简化,永远返回第一个
            return AOP_PROXY;
        }
    }

代码地址

源码地址


相关文章
|
4月前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
AOP(面向切面编程)能够帮助我们在不修改现有代码的前提下,为应用程序添加新的功能或行为。Micronaut框架中的AOP模块通过动态代理机制实现了这一目标。AOP将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高模块化程度。在Micronaut中,带有特定注解的类会在启动时生成代理对象,在运行时拦截方法调用并执行额外逻辑。例如,可以通过创建切面类并在目标类上添加注解来记录方法调用信息,从而在不侵入原有代码的情况下增强应用功能,提高代码的可维护性和可扩展性。
84 1
|
2月前
|
安全 Java 编译器
什么是AOP面向切面编程?怎么简单理解?
本文介绍了面向切面编程(AOP)的基本概念和原理,解释了如何通过分离横切关注点(如日志、事务管理等)来增强代码的模块化和可维护性。AOP的核心概念包括切面、连接点、切入点、通知和织入。文章还提供了一个使用Spring AOP的简单示例,展示了如何定义和应用切面。
171 1
什么是AOP面向切面编程?怎么简单理解?
|
2月前
|
XML Java 开发者
论面向方面的编程技术及其应用(AOP)
【11月更文挑战第2天】随着软件系统的规模和复杂度不断增加,传统的面向过程编程和面向对象编程(OOP)在应对横切关注点(如日志记录、事务管理、安全性检查等)时显得力不从心。面向方面的编程(Aspect-Oriented Programming,简称AOP)作为一种新的编程范式,通过将横切关注点与业务逻辑分离,提高了代码的可维护性、可重用性和可读性。本文首先概述了AOP的基本概念和技术原理,然后结合一个实际项目,详细阐述了在项目实践中使用AOP技术开发的具体步骤,最后分析了使用AOP的原因、开发过程中存在的问题及所使用的技术带来的实际应用效果。
72 5
|
7月前
|
Java Maven 数据安全/隐私保护
详解 Java AOP:面向方面编程的核心概念与 Spring 实现
详解 Java AOP:面向方面编程的核心概念与 Spring 实现
96 1
|
7月前
|
前端开发 Java 数据库
浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~
浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~
|
7月前
|
XML Java 数据格式
技术好文:Spring基础篇——AOP切面编程
技术好文:Spring基础篇——AOP切面编程
|
4月前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
【9月更文挑战第9天】AOP(面向切面编程)通过分离横切关注点提高模块化程度,如日志记录、事务管理等。Micronaut AOP基于动态代理机制,在应用启动时为带有特定注解的类生成代理对象,实现在运行时拦截方法调用并执行额外逻辑。通过简单示例展示了如何在不修改 `CalculatorService` 类的情况下记录 `add` 方法的参数和结果,仅需添加 `@Loggable` 注解即可。这不仅提高了代码的可维护性和可扩展性,还降低了引入新错误的风险。
54 13
|
3月前
|
Java 容器
AOP面向切面编程
AOP面向切面编程
49 0
|
5月前
|
XML Java 数据格式
Spring5入门到实战------11、使用XML方式实现AOP切面编程。具体代码+讲解
这篇文章是Spring5框架的AOP切面编程教程,通过XML配置方式,详细讲解了如何创建被增强类和增强类,如何在Spring配置文件中定义切入点和切面,以及如何将增强逻辑应用到具体方法上。文章通过具体的代码示例和测试结果,展示了使用XML配置实现AOP的过程,并强调了虽然注解开发更为便捷,但掌握XML配置也是非常重要的。
Spring5入门到实战------11、使用XML方式实现AOP切面编程。具体代码+讲解
|
5月前
|
Java Spring XML
掌握面向切面编程的秘密武器:Spring AOP 让你的代码优雅转身,横切关注点再也不是难题!
【8月更文挑战第31天】面向切面编程(AOP)通过切面封装横切关注点,如日志记录、事务管理等,使业务逻辑更清晰。Spring AOP提供强大工具,无需在业务代码中硬编码这些功能。本文将深入探讨Spring AOP的概念、工作原理及实际应用,展示如何通过基于注解的配置创建切面,优化代码结构并提高可维护性。通过示例说明如何定义切面类、通知方法及其应用时机,实现方法调用前后的日志记录,展示AOP在分离关注点和添加新功能方面的优势。
71 0