使用AspectJ提供的实现aop(注解方式)

1.引入spring基础包
2.引入aspectJ的jar包:

   com.springsource.org.aopalliance-*.jar
  com.springsource.org.aspectj.weaver-*.jar

3.实现目标类UserDAO

@Repository("userDao")
public class UserDao {
    //添加用户
    public void addUser(){
        System.out.println("添加用户");
    }
    //删除用户
    public void deleteUser(){
        System.out.println("删除用户");
    }
}

4.定义前面类MyAspect

public class MyAspect {
    //定义切入点
    @Pointcut("execution(* com.aspect.*.*(..))")
    //使用一个返回值为void、方法体为空的方法来命名切入点
    private void myPointCut(){}
    //前置通知
    @Before("myPointCut()")
    public void myBefore(JoinPoint joinPoint) {
        System.out.println("前置通知”模拟执行权限检查.....,");
        System.out.println("目标类是:" + joinPoint.getTarget());
        System.out.println(",被植入增强处理的目标方法为:" + joinPoint.getSignature().getName());
    }

    //后置通知
    @AfterReturning("myPointCut()")
    public void myAfterReturning(JoinPoint joinPoint) {
        System.out.println("后置通知:模拟记录检查日志....,");
        System.out.println("被植入增强处理目标类方法为:" + joinPoint.getSignature().getName());
    }

    //环绕通知
    @Around("myPointCut()")
    public Object myAroud(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        //开始
        System.out.println("环绕开始:执行目标方法之前,模拟开启事务...");
        //执行当前目标方法
        Object obj = proceedingJoinPoint.proceed();
        //结束
        System.out.println("环绕结束:执行目标方法之后,模拟关闭事务...");
        return obj;
    }

    //异常通知
    @AfterThrowing(value = "myPointCut()",throwing = "e")
    public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
        System.out.println("异常通知:" + "出错了" + e.getMessage());
    }

    //最终通知
    @After("myPointCut()")
    public void myAfter() {
        System.out.println("最终通知:模拟方法结束后的释放资源....");
    }
}

5.bean2.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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
  http://www.springframework.org/schema/aop
  http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    <context:annotation-config/>
    <!--指定需要扫描的包,使注解生效-->
    <context:component-scan base-package="com.aspect.annotation"/>
    <!--启动基于注解的声明式AspectJ支持-->
    <aop:aspectj-autoproxy />
</beans>

6.测试类test

public class test {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean2.xml");
        UserDao userDao = (UserDao) applicationContext.getBean("userDao");
        //执行方法
        userDao.addUser();
    }
}

7.实现的效果

前置通知模拟执行权限检查.....,
目标类是:com.aspect.UserDao@29626d54
,被植入增强处理的目标方法为:addUser
环绕开始:执行目标方法之前,模拟开启事务...
添加用户
最终通知:模拟方法结束后的释放资源....
环绕结束:执行目标方法之后,模拟关闭事务...
后置通知:模拟记录检查日志....,
被植入增强处理目标类方法为:addUser

备注:
@Aspect 定义切面类
@Componet 将这个类加入Spring的IOC容器;
切入点表达式execution(* com.aspect.* .*(..))
  第一个 * 号:表示返回类型, * 号表示所有的类型。
  第二个 * 号:表示类名
  (* 与 包后面有一个空格,要不然会报错)
  括号里面表示方法的参数,两个句点表示任何参数。
通知类型
  @Before 前置通知,在方法执行之前执行
  @After 后置通知,在方法执行之后执行
  @AfterRunning 返回通知,在方法返回结果之后执行
  @AfterThrowing 异常通知,在方法抛出异常之后执行
  @Around 环绕通知,围绕着方法执行

实现AOP,目标(target)类就需生成动态代理。注意:
  1、目标类如果实现了某一个接口,那么Spring就会利用JDK类库生成动态代理。
  2、目标类没有实现某一个接口,那么Spring就会利用CGLIB类库直接修改二进制码来生成动态代理,需要引用CGLIB类库

猜你喜欢

转载自blog.csdn.net/weixin_39938767/article/details/79630132