zoukankan      html  css  js  c++  java
  • spring aop入门

    一、何为AOP?

      spring 的两大核心思想无非是 IOC和AOP。那么Spring 的 aop 是神马意思呢?AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,提高代码的灵活性和可扩展性,AOP可以说也是这种目标的一种实现。

    二、有何用途?

      主要用于将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

    有点抽象,下面直接给出实例

    三、Demo

    1、小Demo 整体结构

    2、所需 jar 包

    3、Service 层接口

    1 package com.xpw.service;
    2 
    3 public interface UserService {
    4     public String add(String name);
    5 }

    Service 实现层userServiceImpl代码

    package com.xpw.service.impl;
    
    import com.xpw.service.UserService;
    
    public class UserServiceImpl implements UserService {
        @Override
        public String add(String name) {
            System.out.println("do add...");
            return name;
        }
    }

    切面的“封装”类

    package com.xpw.aspect;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    
    public class UserAspect {
    
        public void doBefore() {
            System.out.println("before do add...");
        }
    
        public void doAfter() {
            System.out.println("after do add...");
        }
        
        public void doAround(ProceedingJoinPoint pjp) throws Throwable{
            System.out.println("before do add in around()");
            
            Object res = pjp.proceed();
            System.out.println("res = " + res);
            
            System.out.println("before do add in around()");
        }
    }

    4、beans.xml的配置

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:aop="http://www.springframework.org/schema/aop"
     5     xsi:schemaLocation="http://www.springframework.org/schema/beans
     6         http://www.springframework.org/schema/beans/spring-beans.xsd
     7         http://www.springframework.org/schema/aop
     8         http://www.springframework.org/schema/aop/spring-aop.xsd">
     9     
    10     <bean id="userAspect" class="com.xpw.aspect.UserAspect"></bean>
    11     
    12     <bean id="userService" class="com.xpw.service.impl.UserServiceImpl"></bean>
    13     
    14     <aop:config>
    15         <!-- 定义切面 -->
    16         <aop:aspect id="myAspect" ref="userAspect">
    20             <aop:pointcut expression="execution(* com.xpw.service.*.*(..))" id="myPointcut"/>
    21             <aop:before method="doBefore" pointcut-ref="myPointcut"/>
    22             <aop:after method="doAfter" pointcut-ref="myPointcut"/>
    23             <aop:around method="doAround" pointcut-ref="myPointcut"/>    
    24         </aop:aspect>
    25     </aop:config>
    26     
    27 </beans>

    5、测试

     1 package com.xpw.aspect;
     2 
     3 import org.junit.Test;
     4 import org.springframework.context.ApplicationContext;
     5 import org.springframework.context.support.ClassPathXmlApplicationContext;
     6 
     7 import com.xpw.service.UserService;
     8 
     9 
    10 public class UserAspetTest {
    11     
    12     private static ApplicationContext ac;
    13     
    14     static{
    15         ac = new ClassPathXmlApplicationContext("beans.xml");
    16     }
    17     
    18     @Test
    19     public void testAspect(){
    20         UserService us = (UserService) ac.getBean("userService");
    21         us.add("威少");
    22     }
    23 }

    6、结果

    before do add...
    before do add in around()
    do add...
    res = 威少
    before do add in around()
    after do add...

    7、结论

    由上面的结果,可以知道,after() < around() 的 优先级 < before() , 其中,around切面方法有返回值,很多时候我们很可能需要这个返回值来做日志处理等等,它的参数为ProceedingJoinPoint 对象 ,通过pjp.getSignature().getName()可以获取切入的方法名,通过pjp.getTarget().getClass().getName()获取切入目标类的名称,通过pjp.getArgs()获取传入的参数

    System.out.println("method = " + pjp.getSignature().getName());
    System.out.println("class name = " + pjp.getTarget().getClass().getName());
    System.out.println("parm = " + pjp.getArgs()[0]);

    Object res = pjp.proceed();在这行代码前面的代码会在执行目标方法(add)时先被执行;而在它之后的代码则是在执行目标方法(如本例中的add())完成后执行。

    当然,before 、 after 、around 没必要一起用,择其一即可

  • 相关阅读:
    搞定Mac Maven
    《数学之美》读书笔记
    Scalable Web Architecture and Distributed Systems
    【程序员】修炼之书
    用平常心,做非常事(字节跳动九周年张一鸣演讲)
    动态规划题目总结
    Spring Boot 启动时,让方法自动执行的 4 种方法!
    MybatisGenerator生成mapper、dao、entity
    HTTPS的GET、POST、PUT、DELETE请求
    SpringBoot使用Slf4j进行日志配置
  • 原文地址:https://www.cnblogs.com/chenmo-xpw/p/3944764.html
Copyright © 2011-2022 走看看