Spring学习笔记day04——AOP(二)

AspectJ简介

  • AspectJ是一个基于Java语言的AOP框架
  • Spring2.0以后新增了对AspectJ切点表达式支持
  • @AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面
  • 新版本Spring框架,建议使用AspectJ方式来开发AOP
  • 主要用途:自定义开发

AspectJ通知类型

aop联盟定义通知类型,具有特性接口,必须实现,从而确定方法名称。
aspectj 通知类型,只定义类型名称,以及方法格式。

  • before:前置通知(应用:各种校验)
    在方法执行前执行,如果通知抛出异常,阻止方法运行
  • afterReturning:后置通知(应用:常规数据处理)
    方法正常返回后执行,如果方法中抛出异常,通知无法执行
    必须在方法执行后才执行,所以可以获得方法的返回值。
  • around:环绕通知(应用:十分强大,可以做任何事情)
    方法执行前后分别执行,可以阻止方法的执行
    必须手动执行目标方法
  • afterThrowing:抛出异常通知(应用:包装异常信息)
    方法抛出异常后执行,如果方法没有抛出异常,无法执行
  • after:最终通知(应用:清理现场)
    方法执行完毕后执行,无论方法中是否出现异常

切入点表达式

  • 语法:execution(修饰符 返回值 包.类.方法名(参数) throws异常)

使用xml文件来实现切入

  • 导包
aopalliance-1.0.0.jarAOP联盟规范
spring-aspects-3.2.0.RC2.jaraspectj实现
spring-aop-3.2.0.jarAOP实现
aspectj.weaver-1.6.jar织入
代码
  • 切面类
package spring.aspect;

/**
 * 切面类:增强代码与切入点的结合
 */
public class MyAspect{
    public void myBefore()
    {
        System.out.println("前置通知...");
    }

}

  • 目标类
package spring.service.impl;

import org.springframework.stereotype.Service;
import spring.service.UserService;

@Service("userService")
public class UserServiceImpl implements UserService {

    @Override
    public void addUser() {
        System.out.println("添加用户");
    }

    @Override
    public void updateUser() {
        System.out.println("更新用户");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }
}

  • 配置beans.xml文件
<?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:context="http://www.springframework.org/schema/context"
               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/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
"
>
    <!--配置UserService-->
    <bean id="userService" class="spring.service.impl.UserServiceImpl"/>
    <!--配置切面对象-->
    <bean id="myAspect" class="spring.aspect.MyAspect"/>

    <!--配置AOP-->
    <aop:config>
        <!--切面-->
        <aop:aspect ref="myAspect">
            <!--切入点-->
            <aop:pointcut id="myPointcut" expression="execution(* spring.service.impl.UserServiceImpl.*(..))"/>

            <!--配置一个前置通知-->
            <aop:before method="myBefore" pointcut-ref="myPointcut"></aop:before>
        </aop:aspect>

    </aop:config>


</beans>
  • 测试类
@Test
    public void test5()
    {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans3.xml");
        UserService service = (UserService) context.getBean("userService");
        service.deleteUser();
    }
}
  • 运行结果
    在这里插入图片描述

使用注解来实现切入

  • 配置beans.xml文件
<?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:context="http://www.springframework.org/schema/context"
               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/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
"
>
    <!--扫描注解位置-->
    <context:component-scan base-package="spring"></context:component-scan>

    <!--AOP注解生效-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  • 使用注解来声明service和切面
package spring.service.impl;

import org.springframework.stereotype.Service;
import spring.service.UserService;


@Service("userService")
public class UserServiceImpl implements UserService {

    @Override
    public void addUser() {
        System.out.println("添加用户");
    }

    @Override
    public void updateUser() {
        System.out.println("更新用户");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }
}

package spring.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 切面类:增强代码与切入点的结合
 */
@Component
@Aspect
public class MyAspect {
    //声明一个公共切入点
    @Pointcut("execution(* spring.service.impl.UserServiceImpl.*(..))")
    public void myPointcut() {}

    //声明前置通知
    @Before("myPointcut()")
    public void myBefore()
    {
        System.out.println("前置通知...");
    }

    //声明后置通知
    @AfterReturning(value = "myPointcut()", returning = "ret")
    public void myAfterReturnning(Object ret){
        System.out.println("后置通知...");
    }

    //声明环绕通知
    @Around(value = "myPointcut()")
    public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕通知前...");
        Object obj = pjp.proceed();//放行
        System.out.println("放行");
        System.out.println("环绕通知后...");
        return obj;
    }

    //声明异常通知
    @AfterThrowing(value = "myPointcut()", throwing = "e")
    public void myAfterThrowing(Throwable e)
    {
        System.out.println("异常通知...");
    }

    //声明最终通知
    @After(value = "myPointcut()")
    public void myAfter(){
        System.out.println("最终通知...");
    }

}

  • 测试类
 @Test
    public void test1()
    {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        UserService service = (UserService) context.getBean("userService");
        service.deleteUser();
    }
  • 运行结果
    在这里插入图片描述

注解总结

  • @Aspect 声明切面,修饰切面类,从而获得 通知。
  • @Before 前置
  • @AfterReturning 后置
  • @Around 环绕
  • @AfterThrowing 抛出异常
  • @After 最终
  • @PointCut ,修饰方法 private void xxx(){} 之后通过“方法名”获得切入点引用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值