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.处理通知中的参数 

原文地址:https://www.cnblogs.com/Shadowplay/p/10155756.html