• Spring使用笔记(四) 面向切面的Spring


    面向切面的Spring

    一、面向切面的概念

    在软件开发中,散布于应用多处的功能被称为横切关注点(cross-cutting concern)。

    通常来讲这些横切关注带点从概念上来讲是与应用逻辑相分离的(但是往往会直接嵌入到应用的业务逻辑中)。

    把这些横切关注点与业务逻辑相互分离正是面向切面编程(AOP)所要解决的问题。

    切面所适用的场景:日志、声明式事务、安全和缓存。

    横切关注点可以被模块化特殊的类,这些类被称为切面。

    1.相关术语

    1)通知(advice):描述了切面的工作及如何工作。通知的类型:

    前置通知(Before)

    后置通知(After)

    返回通知(After-returning)

    异常通知(After-throwing)

    环绕通知(方法调用前后都执行)

    2)连接点(join-point):应用执行时可以插入的一个点,如方法调用时,异常抛出时。

    3)切点(cut-point):切点的定义会匹配通知所要植入的一个或者多个链接点。

    4)切面(Aspect):切面是通知和切点的结合,通知和切点共同定义切面的全部内容----

    它是什么及何时何地完成其内容。

    5)引入(Introduction):

    6)织入(Weaving):把切面应用到目标对象,并创建新的代理的过程。

    2.Spring对AOP的支持

    Spring提供了4种类型的AOP支持

    1.基于代理的经典SpingAOP

    2.纯POJO切面

    3.@AspectJ注解驱动的切面

    4.注入式AspectJ切面

    前三个都是Spring AOP实现的变体,Spring AOP构建在动态代理的基础上,

    因此,Spring对AOP的支持仅仅限于方法层面。

    1.示例使用JavaConfig: 

    public interface Performance {
        void performance();
    }
    public class Actor implements Performance{
        public void performance() {
            System.out.println("An actor is on the stage!!!~!!");
        }
    }
    @Aspect
    public class Audience {
        //定义命名的切点
        @Pointcut("execution(* entity.Actor.performance(..))")
        public void performance() {}
    
        @Before("performance()")
        public void silence() {
            System.out.println("Silence please!");
        }
    
        @Before("performance()")
        public void takeSeats() {
            System.out.println("Take seats please!");
        }
    
        @AfterReturning("performance()")
        public void performanceOver() {
            System.out.println("Performance Over!");
        }
    
        @AfterThrowing("performance()")
        public void wrong() {
            System.out.println("Something wrong with the show!");
        }
    
        /*
        * 在一个通知方法中同时编写前置和后置通知
        * */
        @Around("performance()")
        public void around(ProceedingJoinPoint pjp) {
            System.out.println("Around!! before");
            try {
                   pjp.proceed(); //必须调用该方法,如果不调用会阻塞除了
                  // AfterReturning以外的其他方法
                System.out.println("Around!! after");
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }
    }
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = Aconfig.class)
    public class TestAll {
        @Autowired
        private Performance actor;
        @Test
        public void ts() {
            actor.performance();
            /*Around!! before
            Silence please!
            Take seats please!
            An actor is on the stage!!!~!!
            Around!! after
            Performance Over!*/
        }
    }
    @Configuration
    @EnableAspectJAutoProxy //启用自动代理功能
    public class Aconfig {
        @Bean
        public Audience audience() {
            return new Audience();
        }
    
        @Bean
        public Performance actor() {
            return new Actor();
        }
    }

    2.示例通过XML:

    @Aspect
    public class Audience {
        public void silence() {
            System.out.println("Silence please!");
        }
        public void takeSeats() {
            System.out.println("Take seats please!");
        }
        public void performanceOver() {
            System.out.println("Performance Over!");
        }
        public void wrong() {
            System.out.println("Something wrong with the show!");
        }
        /*
        * 在一个通知方法中同时编写前置和后置通知
        * */
        public void around(ProceedingJoinPoint pjp) {
            System.out.println("Around!! before");
            try {
                   pjp.proceed(); //必须调用该方法,如果不调用会阻塞除了
                  // AfterReturning以外的其他方法
                System.out.println("Around!! after");
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }
    }
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop.xsd">
        <!--目标对象-->
        <bean id="actor" class="entity.Actor" />
        <!--切面对象-->
        <bean id="audience" class="entity.Audience"/>
        <!--切面-->
        <aop:config>
            <!--定义命名的切点-->
            <aop:pointcut expression="execution(* entity.Actor.performance(..))" id="cutRef"/>
            <aop:aspect ref="audience">
                <aop:before method="silence" pointcut-ref="cutRef"/>
                <aop:before method="takeSeats" pointcut-ref="cutRef"/>
                <aop:after-returning method="performanceOver" pointcut-ref="cutRef"/>
                <aop:after-throwing method="wrong" pointcut-ref="cutRef"/>
                <aop:around method="around" pointcut-ref="cutRef"/>
            </aop:aspect>
        </aop:config>
        <aop:aspectj-autoproxy/><!--启用自动代理-->
    </beans>
    @Autowired
    private Performance actor;
    @Test
    public void ts() {
        actor.performance();
        /*Silence please!
        Take seats please!
        Around!! before
        An actor is on the stage!!!~!!
        Around!! after
        Performance Over!*/
    }

    3.处理通知中的参数 

  • 相关阅读:
    雑談
    safari下无法模拟click()的解决方法 ------转载
    用户操作
    居中
    replace 重写
    JS数组添加元素的三种方式
    Asp.Net Core 包
    CSS3 动画 可以参考
    CSS3 动画
    完全居中
  • 原文地址:https://www.cnblogs.com/Shadowplay/p/10155756.html
Copyright © 2020-2023  润新知