Spring(4): AOP

来源:互联网 发布:node网络服务器搭建 编辑:程序博客网 时间:2024/06/06 15:45

1. AOP定义和术语

AOP(Aspect Oriented Programming):面向切面编程。AOP可以把各类的公共行为封装到一个可重用模块,并将其命名为”Aspect”,即切面,便于减少系统的重复代码,降低模块之间的耦合度。常用的主要功能:日志记录,性能统计,安全控制,事务处理,异常处理。

术语介绍:
- 切面(Aspect):是对横切关注点的抽象。
- 切入点(Pointcut):对连接点进行拦截的定义。
- 连接点(Join point):指被拦截到的方法。
- 增强(Advice):指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类。
- 引入(Introduction):引用允许你添加新方法或属性到现有的类中。
- 目标对象(Target object):被一个或者多个方面所通知的对象,这个对象永远是一个被代理对象。
- 织入(Weaving):将切面应用到目标对象并导致代理对象创建的过程。

2. Spring对AOP的支持

Spring AOP 事务管理的2种代理方式:
① 基于 JDK 接口的动态代理;
② 基于 CGLib 动态生成子类的代理。

2.1 使用注解创建切面

AspectJ的风格类似纯java注解的普通java类。AspectJ切面使用@Aspect注解配置,拥有@Aspect的任何bean将被Spring自动识别并应用。
用@Aspect注解的类可以有方法和字段,他们也可能包括切入点(pointcut),增强(Advice)和引入(introduction)声明。
@Aspect注解不能通过类路径自动检测发现,需要配合使用@Component注释或者在xml配置bean。

代码:

1.定义切面代码

@Aspectpublic class Audience {    @Pointcut("execution(* com.chen.aop.Concert.perform(..))")    public void performance() {    }    @Before("performance()")    public void slienceCellPhones() {        System.out.println("Silencing cell phones.");    }    @After("performance()")    public void takeSeats() {        System.out.println("Leaving away.");    }    @AfterReturning("performance()")    public void applause() {        System.out.println("CLAP CLAP CLAP!!!");    }    @AfterThrowing("performance()")    public void demandRefund() {        System.out.println("Demanding a refund.");    }}

说明:
@Aspect:表明类PreGreetingAspect不仅仅是一个POJO,还是一个切面。
@Pointcut:在切面内定义可重用的切点。

2.配置代码

@Configuration@EnableAspectJAutoProxy(proxyTargetClass = true)public class AopConfig {    @Bean    public Concert concert() {        return new Concert();    }    @Bean    public Audience audience(){        return new Audience();    }}

说明:
@EnableAspectJAutoProxy:注解启动自动代理功能。proxyTargetClass默认为false,表示使用JDK动态代理技术织入增强;当配置为true时,表示使用CGLib动态代理技术织入增强。

3.测试代码

@RunWith(SpringRunner.class)@SpringBootTest@ContextConfiguration(classes = AopConfig.class)public class ConcertTest {    @Autowired    private Concert concert;    @Test    public void testPerform() {        assertNotNull(concert);        concert.perform();    }    @Test    public void testPerformByAutoProxy() {        Concert target = new Concert();        AspectJProxyFactory factory = new AspectJProxyFactory();        // 1.设置目标对象        factory.setTarget(target);        // 2.添加切面类        factory.addAspect(Audience.class);        // 3.生成织入切面的代理对象        Concert concert = factory.getProxy();       concert.perform();    }}

AspectJ提供的5个注解:

  1. @Before:增强方法会在目标方法调用之前执行;
  2. @Around:增强方法将目标方法封装起来;
  3. @After:增强方法会在目标方法返回或抛出异常后调用;
  4. @AfterReturning:增强方法会在目标方法返回后调用;
  5. @AfterThrowing:增强方法会在目标方法抛出异常后调用。

2.2 使用XML配置AOP

Spring所有的切面和增强都必须放在一个<aop:config>内(可以配置包含多个<aop:config> 元素),每一个<aop:config>可以包含pointcut,advisor和aspect元素,它们必须按照这个顺序进行声明。
<aop:config>使用Spring的自动代理机制。
代码:

<?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"       xsi:schemaLocation="http://www.springframework.org/schema/beans                           http://www.springframework.org/schema/beans/spring-beans.xsd                           http://www.springframework.org/schema/aop                           http://www.springframework.org/schema/aop/spring-aop.xsd">    <!--基于@Aspect切面的驱动器-->    <aop:aspectj-autoproxy proxy-target-class="true"/>    <!--目标Bean-->    <bean id="concert" class="com.chen.aop.Concert"/>    <bean id="audience" class="com.chen.aop.Audience"/>    <aop:config>        <aop:aspect ref="audience">            <aop:pointcut id="performance" expression="execution(* com.chen.aop.Concert.perform(..))"/>            <aop:before pointcut-ref="performance" method="silenceCellPhones"/>            <aop:after pointcut-ref="performance" method="leaveAway"/>            <aop:after-returning pointcut-ref="performance" method="applause"/>            <aop:after-throwing pointcut-ref="performance" method="demandRefund"/>            <aop:around pointcut-ref="performance" method="watchPerformance"/>        </aop:aspect>    </aop:config></beans>

源代码:
https://github.com/leifchen/hello-spring
代码包:com.chen.aop

原创粉丝点击