AspectJ的注解开发AOP

1.AspectJ简介
图片说明

2.环境配置

<?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"> <!-- bean definitions here -->
<!--开启aspectJ的注解开发,自动代理==========-->
    <aop:aspectj-autoproxy/>
</beans>

3.AspectJ通知类型
图片说明
4.在通知中通过value属性定义切点
图片说明
注意访问修饰符可有可无,..也是任意
5.入门案例(前置通知)

  • pom.xml文件中导入相应的依赖

  • 编写目标类和切面类
    目标类:ProductDao,老样子
    切面类:

    @Aspect
    public class MyAspectAnno {
      @Before(value = "execution(* com.imooc.aspectJ.demo1.ProductDao.save(..))")
      public void before() {
          System.out.println("前置通知");
      }
    }
  • 1.@Aspect:代表的是这个类是切面类2.@Before(里面添加execution函数定义要切入点)*

  • 编写applicationContext文件

    <!--开启aspectJ的注解开发,自动代理==========-->
    <aop:aspectj-autoproxy/>
      <!--定义目标类-->
      <bean id="productDao" class="com.imooc.aspectJ.demo1.ProductDao"/>
      <!--定义切面类-->
      <bean id="myAspectAnno" class="com.imooc.aspectJ.demo1.MyAspectAnno"/>
    </beans>
  • 编写测试类

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class SpringDemo1 {
      @Resource(name = "productDao")
      private ProductDao productDao;
      @Test
      public void demo1() {
          productDao.save();
          productDao.delete();
          productDao.findAll();
          productDao.findOne();
          productDao.update();
      }
    }
  • 也可以在增强的方法中传入JoinPoint获取切点信息(注意要导入org.aspectj.lang.JoinPoint的包)

    @Before(value = "execution(* com.imooc.aspectJ.demo1.ProductDao.save(..))")
      public void before(JoinPoint joinPoint) {
          System.out.println("前置通知" + joinPoint);
      }

6.其他通知的使用

  • AfterReturn 通过return属性可以定义方法的返回值作为参数
@AfterReturning(value = "execution(* com.imooc.aspectJ.demo1.ProductDao.save(..))")
    public void afterReturing(Object result){
        System.out.println("后置通知=================="+result);
    }

-Around环绕通知
around方法的返回值就是目标代理方法执行返回值
参数为ProceedingJoinPoint可以调用拦截目标方法执行

 @Around(value = "execution(* com.imooc.aspectJ.demo1.ProductDao.save(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前通知================");
        Object obj = joinPoint.proceed(); // 执行目标方法
        System.out.println("环绕后通知================");
        return obj;
    }
  • AfterThrowing 异常抛出通知
    图片说明
  • After 最终通知
    @After(value=value = "execution(* com.imooc.aspectJ.demo1.ProductDao.findAll(..))")
      public void after(){
          System.out.println("最终通知==================");
      }
  • 无论目标方法是否有异常 都会执行*

7.通过PointCut为切点命名
图片说明
在增强类中,添加一个标签,Pointcut

@Pointcut(value="execution(* com.imooc.aspectJ.demo1.ProductDao.save(..))")
    private void myPointcut1(){}

AspectJ的XML方式开发AOP

入门案例

  • 编写目标类和切面类(增强类)
    目标类老生常谈了。切面类:不需要添加标签

  • 编写applicationContext的xml文件

     <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"> <!-- bean definitions here -->
    
      <!--定义目标类-->
      <bean id="customDao" class="com.imooc.aspectJ.demo2.CustomDaoImpl"/>
      <!--定义切面类-->
      <bean id="myAspectXml" class="com.imooc.aspectJ.demo2.MyAspectXml"/>
      <!--aop的相关配置-->
      <aop:config>
          <!--配置切入点-->
          <aop:pointcut id="pointcut1" expression="execution(* com.imooc.aspectJ.demo2.CustomDaoImpl.save(..))"/>
          <!--配置aop的切面-->
          <aop:aspect ref="myAspectXml">
              <!--配置前置增强-->
              <aop:before method="before" pointcut-ref="pointcut1"/>
          </aop:aspect>
      </aop:config>
    </beans> 
  • 这里要多配置一下aop的相关配置
    1.aop:config
    2.配置切入点
    3.配置aop切面,配置增强方法

1.后置通知 + result

<!--xml中配置后置增强-->
            <aop:after-returning method="afterReturning" pointcut-ref="pointcut2" returning="result"/>

//切面类中后置通知
    public void afterReturning(Object result) {
        System.out.println("xml方式的后置通知" + result);
    }

2.环绕通知

  • 在增强面的代码中
    //环绕通知
      public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
          System.out.println("xml方式的环绕前通知");
          Object obj = joinPoint.proceed();//执行目标方法
          System.out.println("xml方式的环绕后通知");
          return obj;
      }
  • 在xml文件中
    <!--配置切入点-->
    <aop:pointcut id="pointcut3" expression="execution(* com.imooc.aspectJ.demo2.CustomDaoImpl.delete())"/>
  • 在切入面中
    <!--配置环绕增强-->
        <aop:around method="around" pointcut-ref="pointcut3"/>

3.异常抛出通知

  • 程序有异常时,执行

    //异常抛出通知
      public void afterThrowing(Throwable e) {
          System.out.println("xml方式的异常抛出通知" + e.getMessage());
    
      }
    

//xml中==================

<aop:pointcut id="pointcut4" expression="execution(* com.imooc.aspectJ.demo2.CustomDaoImpl.findOne())"/>


<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="e"/>

```

4.最终通知

  • 无论程序有无异常都会执行
    标签:aop:after