美文网首页
spring AOP 编程式应用

spring AOP 编程式应用

作者: lotusfan2018 | 来源:发表于2018-07-15 21:01 被阅读0次

    一、spring AOP 和 AspectJ

    spirng AOP: 是基于对象代理模式进行织入逻辑代码,但对于static和final方法上应用织入是无法做到的
    AspectJ :其是一个独立的在编辑期进行逻辑代码的织入框架,不受限于必须获取代理

    二、AOP织入

    1. Advice、Pointcut、Advisor、ProxyFactory

    Advice (通知)是AOP联盟定义的一个接口,描述了连接点做什么,为切面增强提供织入接口。编写逻辑代码的基类
    Pointcut (切点)决定Advice通知应该作用于哪个连接点。也就是说这些连接点集合(决定切入的方法)是通过Pointcut来决定的
    Advisor (通知器)是对Advice和Pointcut的整合,作为IoC容器使用AOP的基础设施。所有
    ProxyFactory(生成代理对象的工厂类)可以让我们通过编程式的方法实现spirng AOP功能
    在spring中有三个代理工厂类,除了上面提到的还有ProxyFactoryBean(声明式应用)、AspectJProxyFactory(AspectJ应用),它们都继承了ProxyCreatorSupport类

    2. 应用演示

    目标类,提供切入点

    class TargetImpl {
        public void print() {
            System.out.println("this is target");
        }
    }
    
    MethodInterceptor

    MethodInterceptor是一个最基础的继承自->Interceptor->Advice的通知类。ProxyFactory生成bean代理有jdk proxy和Cglib两种方式,但spirng把它们的回调都统一封装,回调执行MethodInterceptor的invoke方法
    具体封装在了ReflectiveMethodInvocation里,执行process来调起invoke

        private static void basics() {
    
            Advice advice = (MethodInterceptor) (invocation) -> {
                System.out.println("enter advice->interceptor->methodInterceptor");
                return invocation.proceed();
            };
    
    
            Pointcut pointcut = new Pointcut() {
                @Override
                public ClassFilter getClassFilter() {
                    return ClassFilter.TRUE;
                }
    
                @Override
                public MethodMatcher getMethodMatcher() {
                    return MethodMatcher.TRUE;
                }
            };
            Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
    
            ProxyFactory proxyFactory = new ProxyFactory(new TargetImpl());
            proxyFactory.addAdvisor(advisor);
    
            TargetImpl target = (TargetImpl) proxyFactory.getProxy();
            target.print();
        }
    

    代码中出现的DefaultPointcutAdvisor是spirng提供的一个默认通知器

    MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor
      private static void before() {
            Advice advice = new MethodBeforeAdviceInterceptor((method, objects, o) -> System.out.println("enter before advice"));
            ProxyFactory proxyFactory = new ProxyFactory(new TargetImpl());
            proxyFactory.addAdvice(advice);
    
            TargetImpl target = (TargetImpl) proxyFactory.getProxy();
            target.print();
    
        }
    
       private static void after() {
    
            Advice advice = new AfterReturningAdviceInterceptor((rv, method, objects, o) -> System.out.println("enter after advice"));
            ProxyFactory proxyFactory = new ProxyFactory(new TargetImpl());
            proxyFactory.addAdvice(advice);
    
            TargetImpl target = (TargetImpl) proxyFactory.getProxy();
            target.print();
    
    
        }
    

    ProxyFactory虽然可以直接添加Advice,但这并不表示它不需要Ponitcut的实现。阅读add方法源码可以看到它会生成一个默认的DefaultPointcutAdvisor添加在addAdvisor列表里

    @Override
        public void addAdvice(int pos, Advice advice) throws AopConfigException {
            Assert.notNull(advice, "Advice must not be null");
            if (advice instanceof IntroductionInfo) {
                // We don't need an IntroductionAdvisor for this kind of introduction:
                // It's fully self-describing.
                addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
            }
            else if (advice instanceof DynamicIntroductionAdvice) {
                // We need an IntroductionAdvisor for this kind of introduction.
                throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
            }
            else {
                addAdvisor(pos, new DefaultPointcutAdvisor(advice)); //创建默认Advisor
            }
        }
    
    AspectJExpressionPointcut

    spring通过AspectJExpressionPointcut来定义实现AspectJ中的切点语言

     private static void aspectjBefore() {
            TargetImpl target = new TargetImpl();
            AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
            pointcut.setExpression("execution( * com.programmatic.springprogrammatic.TargetImpl.print(..) )");
            Advice advice = new MethodBeforeAdviceInterceptor(new MethodBeforeAdvice() {
                @Override
                public void before(Method method, Object[] args, Object target) throws Throwable {
                    System.out.println("enter before advice");
                }
            });
    
            Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
            ProxyFactory proxyFactory = new ProxyFactory(target);
            proxyFactory.addAdvisor(advisor);
    
    
            TargetImpl proxyTarget = (TargetImpl) proxyFactory.getProxy();
            proxyTarget.print();
    
        }
    

    结语

    spring AOP可以说是通过两个流程来实现对代码的切入和执行逻辑代码。
    (1)通知器的装配;spring AOP会把要切入点的位置和逻辑代码封装为一个标准调用流程。
    (2)生成代理类的时候注入通知器;这样代理类在回调方法时就会运行切入逻辑代码了。
    编程式的实现spring AOP是最基础的运用,它可以更好的使我们看到实现spring AOP装配过程,为更好的理解spring AOP作为一个基础篇

    github地址:https://github.com/lotusfan/spring-programmatic ->ProxyFactoryTest

    相关文章

      网友评论

          本文标题:spring AOP 编程式应用

          本文链接:https://www.haomeiwen.com/subject/sqcmpftx.html