JavaWeb学习:Spring的AOP的开发(AspectJ的XML的方式)

  • AOP的相关术语
    • 连接点:可以被拦截的点。
    • 切入点:真正被拦截的点。
    • 通知:增强方法
    • 引介:类的增强
    • 目标:被增强的对象
    • 织入:将增强应用到目标的过程。
    • 代理:织入增强后产生的对象
    • 切面:切入点和通知的组合

一、创建Web项目,引入jar包

  

  • Spring 核心jar包
    • com.springsource.org.apache.commons.logging-1.1.1.jar
    • spring-beans-5.2.9.RELEASE.jar
    • spring-context-5.2.9.RELEASE.jar
    • spring-core-5.2.9.RELEASE.jar
    • spring-expression-5.2.9.RELEASE.jar
  • Spring IOC、AOP核心jar包
    • spring-aop-5.2.9.RELEASE.jar
  • JUnit5 核心jar包
    • spring-test-5.2.9.RELEASE.jar  Spring整合单元测试的jar包
  • Spring  AspectJ核心jar包
    • spring-aspects-5.2.9.RELEASE.jar    spring和aspectj整合的jar包
    • com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar      AspectJ的jar包

二、创建类

public interface ProductDao {
    public void save();
    public void find();
    public void update();
    public void delete();
}
public class ProductDaoImpl implements ProductDao {
    @Override
    public void save() {
    System.out.println("保存商品...");
    }

    @Override
    public void find() {
    System.out.println("查询商品...");
    }

    @Override
    public void update() {
    System.out.println("修改商品...");
    }

    @Override
    public void delete() {
    System.out.println("删除商品...");
    }
}

三、配置Spring (将类交给Spring管理)

  ①、设置XML约束

    spring-framework-5.2.9.RELEASE\docs\spring-framework-reference\core.html#xsd-schemas-aop

       

   ②、将类交给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 
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop 
        https://www.springframework.org/schema/aop/spring-aop.xsd">


    <bean id="productDao" class="com.xxx.spring.dao.ProductDaoImpl"/>
    
    
</beans>

  ③、编写测试类

    引入了Spring整合JUnit的jar包,就不用我们手动创建ApplicationContext对象了

@SpringJUnitConfig(locations = "classpath:bean.xml")//JUnit5
public class SpringDemo {
    @Autowired
    private ProductDao productDao;
    @Test
    public void demo1() {
       productDao.save();
       productDao.find();
       productDao.update();
       productDao.delete();
       
       }
} 
保存商品...
查询商品...
修改商品...
删除商品...

  ④、编写切面类(增强方法所在的对象)

public class AspectXML {
    public void checkPri() {
    System.out.println("权限验证方法======");
    }
}

  ⑤、通过配置完成AOP

    <!-- 将切面类交给Spring管理 -->
    <bean id="aspectXML" class="com.xxx.spring.dao.AspectXML"/>

    <!-- 通过AOP的配置完成对目标类产生代理 -->
    <aop:config>
        <!-- expression:指定要增强的方法 -->
        <aop:pointcut expression="execution(* com.xxx.spring.dao.ProductDaoImpl.save(..))"
            id="product_save" />
        <!-- 配置切面  ref="aspectXML" 指定切面类-->
        <aop:aspect ref="aspectXML">
            <!-- 切面类中的增强方法对应的切入点 -->
            <aop:before method="checkPri" pointcut-ref="product_save" />
        </aop:aspect>
    </aop:config>

  ⑥、执行③中测试方法

权限验证方法======
保存商品...
查询商品...
修改商品...
删除商品...

四、解析<aop:config>

    <!-- 将切面类交给Spring管理 -->
    <bean id="aspectXML" class="com.xxx.spring.dao.AspectXML"/>

    <!-- 通过AOP的配置完成对目标类产生代理 -->
    <aop:config>
        <!-- expression:指定要增强的方法 -->
        <aop:pointcut expression="execution(* com.xxx.spring.dao.ProductDaoImpl.save(..))" id="product_save" />
        <!-- 配置切面  ref="aspectXML" 指定切面类-->
        <aop:aspect ref="aspectXML">
            <!-- 前置通知 -->
            <aop:before method="checkPri" pointcut-ref="product_save" />
            <!-- 后置通知 -->
            <aop:after-returning method=""/>
            <!-- 环绕通知 -->
            <aop:around method=""/>
            <!-- 异常通知 -->
            <aop:after-throwing method=""/>
            <!-- 最终通知 -->
            <aop:after method=""/>
        </aop:aspect>
    </aop:config>

  ①、配置切面类,为切入点提供增强方法

<bean id="aspectXML" class="com.xxx.spring.dao.AspectXML"/>

  ②、通过表达式设置切入点

<aop:pointcut expression="execution(* com.xxx.spring.dao.ProductDaoImpl.save(..))" id="product_save" />
  • 基于execution函数的表达式语法:
    • [访问修饰符] 方法返回值 包名.类名.方法名(参数)
    • [public] void com.xxx.spring.dao.ProductDaoImpl.save(..)    
    • * *.*.*.*DaoImpl.save(..) ----所有DaoImpl类中的save方法
    • * com.xxx.spring.dao.ProductDaoImpl+.save(..)  ----当前ProductDaoImpl类和其子类中的save方法
    • * com.xxx.spring..*.*(..) -- 当前spring包和其子包下所有类中的所有方法

  ③、指定切面类,设置切入点需要增强方法增强方法的执行规则

        <aop:aspect ref="aspectXML">
            <!-- 前置通知 -->
            <aop:before method="" pointcut-ref="" />
            <!-- 后置通知 -->
            <aop:after-returning method=""/>
            <!-- 环绕通知 -->
            <aop:around method=""/>
            <!-- 异常通知 -->
            <aop:after-throwing method=""/>
            <!-- 最终通知 -->
            <aop:after method=""/>
        </aop:aspect>

    Ⅰ、前置通知

<aop:pointcut expression="execution(* com.xxx.spring.dao.ProductDaoImpl.save(..))" id="product_save" />
<aop:before method="checkPri" pointcut-ref="product_save" />
    /**
     * 前置通知
     * 获取切入点信息
     */
    public void checkPri(JoinPoint joinPoint) {
    System.out.println("权限验证======"+joinPoint);
    }

    Ⅱ、后置通知

    @Override
    public String delete() {
    System.out.println("删除商品...");
    return "delete";
    }

 

<aop:pointcut expression="execution(* com.xxx.spring.dao.ProductDaoImpl.delete(..))" id="product_delete" />
<!-- 后置通知 -->
<aop:after-returning method="writeLog" pointcut-ref="product_delete" returning="result"/>
    /**
     * 后置通知
     * 获取切入点返回值
     */
    public void writeLog(Object result) {  //Object result和上面配置文件中的returning="result"要一致
    System.out.println("日志记录======"+result);
    }
    

    Ⅲ、环绕通知

<aop:pointcut expression="execution(* com.xxx.spring.dao.ProductDaoImpl.update(..))" id="product_update" />
<!-- 环绕通知 -->
<aop:around method="checkPerformance" pointcut-ref="product_update"/>
    /**
     * 环绕通知
     * 获取切入点
     * @throws Throwable 
     * 
     */
    public Object checkPerformance(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("性能检测前======");
    Object obj=joinPoint.proceed();
    System.out.println("性能检测后======");
    return obj;
    }

    Ⅳ、异常通知

    @Override
    public void find() {
    System.out.println("查询商品...");
    int i=1/0;
    }

 

<aop:pointcut expression="execution(* com.xxx.spring.dao.ProductDaoImpl.find(..))" id="product_find" />
<!-- 异常通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="product_find" throwing="ex"/>
    /**
     * 异常抛出通知
     * 获取异常信息
     */
    public void afterThrowing(Throwable ex) {//Throwable ex与上面配置中的throwing="ex"值要一致
    System.out.println("异常抛出通知======"+ex.getMessage());
    }

    Ⅴ、最终通知(无论切入点是否有异常都会执行)

<aop:pointcut expression="execution(* com.xxx.spring.dao.ProductDaoImpl.find(..))" id="product_find" />
<!-- 最终通知 -->
<aop:after method="after" pointcut-ref="product_find"/>
    /**
     * 最终通知
     */
    public void after() {
    System.out.println("最终通知======");
    }

    最终结果:

权限验证======execution(void com.xxx.spring.dao.ProductDao.save())
保存商品...
性能检测前======
修改商品...
性能检测后======
删除商品...
日志记录======delete
查询商品...
最终通知======
异常抛出通知======/ by zero
  • AOP的入门开发
  • 引入jar包
  • 编写目标类并配置交给Spring管理
  • 编写切面类并配置交给Spring管理
  • 进行aop的配置
  • <aop:config>
        <aop:pointcut expression=”execution(表达式)” id=”pc1”/>
        <aop:aspect>
             <aop:before method=”” pointcut-ref=”pc1”/>
        </aop:aspect>
    </aop:config>

     

posted @ 2020-12-11 15:20  一杯水M  阅读(160)  评论(0编辑  收藏  举报