Spring-AOP

文章目录

1.基本介绍

1.什么是AOP?
2.示意图
3.五种通知

2.AOP快速入门

1.入门案例
1.导入jar包
2.Cal.java 接口
java 复制代码
package com.sxs.spring.aop.aspectj;

/**
 * 计算数量的接口
 *
 * @author 孙显圣
 * @version 1.0
 */
public interface Cal {
    public double getSub(double num1, double num2);
    public double getSum(double num1, double num2);
}
3.CalImpl.java 实现类
java 复制代码
package com.sxs.spring.aop.aspectj;

import org.springframework.stereotype.Component;

/**
 * @author 孙显圣
 * @version 1.0
 */

@Component //注解创建bean对象
public class CalImpl implements Cal {
    @Override
    public double getSub(double num1, double num2) {
        System.out.println("方法内部打印:" + (num1 - num2));
        return num1 - num2;
    }

    @Override
    public double getSum(double num1, double num2) {
        System.out.println("方法内部打印:" + (num1 + num2));
        return num1 + num2;
    }
}
4.CalAspect.java 切面类
java 复制代码
package com.sxs.spring.aop.aspectj;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 切面类
 *
 * @author 孙显圣
 * @version 1.0
 */
@Component //自动创建bean对象
@Aspect //切面类
public class CalAspect {
    /**
     * @param joinPoint 保存了要切入的方法的信息
     * @Before 前置通知
     * execution(。。。) 切入表达式,表明要切入的方法,格式:格式:访问修饰符+返回类型 全类名 方法名(参数类型)
     */
    @Before(value = "execution(public double com.sxs.spring.aop.aspectj.CalImpl.getSub(double, double))")
    public void before(JoinPoint joinPoint) {
        //获取方法签名
        Signature signature = joinPoint.getSignature();
        System.out.println("方法执行开始-日志-方法名-" + signature.getName()
                + "-参数" + Arrays.asList(joinPoint.getArgs()));
    }

    /**
     * @param joinPoint 保存了要切入的方法的信息
     * @AfterReturning 返回通知
     */
    @AfterReturning(value = "execution(public double com.sxs.spring.aop.aspectj.CalImpl.getSub(double, double))")
    public void afterReturning(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        System.out.println("方法执行正常结束-日志-方法名-" + signature.getName()
        );
    }

    /**
     * @param joinPoint
     * @AfterThrowing 异常通知
     */
    @AfterThrowing(value = "execution(public double com.sxs.spring.aop.aspectj.CalImpl.getSub(double, double))")
    public void throwing(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        System.out.println("方法出现异常-日志-方法名-" + signature.getName()
        );
    }

    /**
     * @param joinPoint
     * @After 后置通知
     */
    @After(value = "execution(public double com.sxs.spring.aop.aspectj.CalImpl.getSub(double, double))")
    public void after(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        System.out.println("方法最终执行完毕-日志-方法名-" + signature.getName()
        );
    }
}
5.beans06.xml 开启注解功能
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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--扫描普通注解-->
    <context:component-scan base-package="com.sxs.spring.aop.aspectj"/>
<!--开启基于aop的注解功能-->
    <aop:aspectj-autoproxy/>
</beans>
6.测试
java 复制代码
package com.sxs.spring.aop.aspectj;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class AopAspectjTest {
    public static void main(String[] args) {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans06.xml");
        //注意:这里需要使用接口类型来获取代理对象,然后使用代理对象来执行方法,才能实现切面编程
        Cal bean = ioc.getBean(Cal.class);
        bean.getSub(1,22);
    }
}
2.细节说明
3.AOP理解(重点)
1.使用场景

需要对接口对象/普通对象的方法进行额外的操作而不想修改源代码时使用

2.代理对象理解

从接口类型或者接口对象id获取的bean对象的运行类型都是代理对象,编译类型是接口类型,最终执行方法的对象是代理对象

一个代理对象对应一个接口对象,在只有一个接口对象的时候才能使用类型来获取

3.AOP的实现方式
  1. 编写接口
  2. 编写实现类,使用注解自动创建bean对象
  3. 编写切面类,使用注解
    1. 自动创建bean对象
    2. 标识切面类
    3. 通知 + 切入表达式(切点)
  4. 编写xml文件
    1. 扫描普通注解
    2. 开启aop注解功能
  5. 使用方式
    1. 使用id或者类型获取针对接口的代理对象
    2. 使用代理对象执行方法
4.简化的AOP实现方式
  1. 接口,接口对象(注解)
  2. 切面(注解),切面对象(注解)
  3. 通知 + 切点
  4. 使用方式
    1. 使用id或者类型获取针对接口的代理对象
    2. 使用代理对象执行方法
4.课后练习
1.题目
2.答案
1.UsbInterface.java
java 复制代码
package com.sxs.spring.aop.homework01;

/**
 * @author 孙显圣
 * @version 1.0
 */
public interface UsbInterface {
    public void work();
}
2.Camera.java
java 复制代码
package com.sxs.spring.aop.homework01;

import org.springframework.stereotype.Component;

/**
 * @author 孙显圣
 * @version 1.0
 */
@Component
public class Camera implements UsbInterface{
    @Override
    public void work() {
        System.out.println("相机正在工作。。。。。。");
    }
}
3.Phone.java
java 复制代码
package com.sxs.spring.aop.homework01;

import org.springframework.stereotype.Component;

/**
 * @author 孙显圣
 * @version 1.0
 */
@Component
public class Phone implements UsbInterface{
    @Override
    public void work() {
        System.out.println("手机正在工作。。。。。。");
    }
}
4.Aspect.java
java 复制代码
package com.sxs.spring.aop.homework01;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
 * @author 孙显圣
 * @version 1.0
 */
@Component
@org.aspectj.lang.annotation.Aspect
public class Aspect {
    @Before(value = "execution(* com.sxs.spring.aop.homework01.*.*(..))")
    public void before(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        System.out.println("日志-方法执行前-方法名-" + signature.getName());
    }
}
5.beans06.xml
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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--扫描普通注解-->
    <context:component-scan base-package="com.sxs.spring.aop.homework01"/>
<!--开启基于aop的注解功能-->
    <aop:aspectj-autoproxy/>
</beans>
6.测试
java 复制代码
package com.sxs.spring.aop.homework01;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class test {
    public static void main(String[] args) {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans06.xml");
        //通过id获取代理对象
        UsbInterface bean1 = (UsbInterface) ioc.getBean("camera");
        //执行方法
        bean1.work();
        //通过id获取代理对象
        UsbInterface bean2 = (UsbInterface) ioc.getBean("phone");
        //执行方法
        bean2.work();
    }
}

3.切入表达式

1.基本介绍
2.举例说明
3.注意事项和细节(重点)
1.切入表达式格式
java 复制代码
*(访问修饰符(空格)返回类型)(空格)*(全类名/接口名/简单类名/简单接口名).*(方法名)(..)(参数类型)
简称: 星 星点星(点点)    
注意:
  • 访问修饰符和返回类型可以使用单个*****来表示任意的,必须满足中间有空格,比如 public * ...
  • 使用简单类名/简单接口名则必须与切面类在同一个包下
  • 如果配置了接口类型,则包括接口对象的所有方法
2.细节
3.Proxy和CGlib的区别
  • Proxy是针对接口的代理对象,可以执行接口的所有方法
  • CGlib是针对父类的代理对象,可以执行该类的所有法

4.JoinPoint常用方法

1.基本介绍
2.代码实例(使用普通对象)
1.Car.java
java 复制代码
package com.sxs.spring.aop.joinpoint;

import org.springframework.stereotype.Component;

/**
 * @author 孙显圣
 * @version 1.0
 */
@Component
public class Car {
    public void run() {
        System.out.println("Car在运行!");
    }
}
2.Aspect02.java
java 复制代码
package com.sxs.spring.aop.joinpoint;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.springframework.stereotype.Component;

/**
 * @author 孙显圣
 * @version 1.0
 */
@Component
@org.aspectj.lang.annotation.Aspect
public class Aspect02 {
    //返回通知
    @AfterReturning(value = "execution(* Car.run())")
    public void afterReturning(JoinPoint joinPoint) {
        System.out.println("方法执行完毕!");
        Signature signature = joinPoint.getSignature();
        System.out.println("name=" + signature.getName());
        System.out.println("simpleName=" + signature.getDeclaringType().getSimpleName());
        System.out.println("该方法所属类的类名=" + signature.getDeclaringTypeName());
        System.out.println("参数=" + joinPoint.getArgs());
    }
}
3.beans06.xml
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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--扫描普通注解-->
    <context:component-scan base-package="com.sxs.spring.aop.joinpoint"/>
<!--开启基于aop的注解功能-->
    <aop:aspectj-autoproxy/>
</beans>
4.test.java
java 复制代码
package com.sxs.spring.aop.joinpoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class test {
    public static void main(String[] args) {
        //获取针对父类的代理对象
        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans06.xml");
        Car bean = ioc.getBean(Car.class);
        bean.run();
    }
}

5.返回通知获取结果

代码实例
修改Aspect02.java
java 复制代码
package com.sxs.spring.aop.joinpoint;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.springframework.stereotype.Component;

/**
 * @author 孙显圣
 * @version 1.0
 */
@Component
@org.aspectj.lang.annotation.Aspect
public class Aspect02 {
    /**
     * 返回通知获取结果
     *
     * @param joinPoint
     * @param res 参数名必须与returning的一致
     */
    @AfterReturning(value = "execution(* Car.run())", returning = "res")
    public void afterReturning(JoinPoint joinPoint, Object res) {
        System.out.println("返回结果为=" + res);
    }
}

6.异常通知获取异常

代码实例
1.修改Car.java
2.修改Aspect02.java
java 复制代码
    /**
     * 异常通知获取异常
     *
     * @param joinPoint
     * @param throwable 参数名必须与throwing一致
     */
    @AfterThrowing(value = "execution(* Car.run())", throwing = "throwable")
    public void afterThrowing(JoinPoint joinPoint, Throwable throwable) {
        System.out.println("异常通知获取异常:" + throwable);
    }

7.环绕通知

代码实例
1.Dog.java
java 复制代码
package com.sxs.spring.aop.doArround;


import org.springframework.stereotype.Component;

/**
 * @author 孙显圣
 * @version 1.0
 */
@Component
public class Dog {
    public String sayHi(String name) {
        System.out.println(name + "wang,wang!");
        return name + "wang,wang!";
    }
}
2.Aspect03.java
java 复制代码
package com.sxs.spring.aop.doArround;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
 * 环绕通知
 *
 * @author 孙显圣
 * @version 1.0
 */
@Component
@Aspect
public class Aspect03 {
    /**
     * @param joinPoint 连接点对象
     * @return 返回结果
     */
    @Around(value = "execution(public String sayHi(String))")
    public Object doArround(ProceedingJoinPoint joinPoint) {
        Object result = null;
        String methodName = joinPoint.getSignature().getName();
        try {
            Object[] args = joinPoint.getArgs();
            List<Object> list = Arrays.asList(args);
            //1.前置通知
            System.out.println("AOP环绕通知-前置通知-方法名=" + methodName + "-参数-" + list);
            //执行方法
            result = joinPoint.proceed();
            //2.返回通知
            System.out.println("AOP环绕通知-返回通知-方法名=" + methodName + "-结果为=" + result);
        } catch (Throwable e) {
            //3.异常通知
            System.out.println("AOP环绕通知-异常通知-方法名=" + methodName + "-异常=" + e);
        } finally {
            //4.后置通知
            System.out.println("AOP环绕通知-后置通知-方法名=" + methodName);
        }
        return result;
    }
}
3.beans06.xml
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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--扫描普通注解-->
    <context:component-scan base-package="com.sxs.spring.aop.doArround"/>
<!--开启基于aop的注解功能-->
    <aop:aspectj-autoproxy/>
</beans>
4.Test.java
java 复制代码
package com.sxs.spring.aop.doArround;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class Test {
    public static void main(String[] args) {
        //读取配置文件获取容器
        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans06.xml");
        //获取针对父类的代理对象
        Dog bean = ioc.getBean(Dog.class);
        //执行方法
        bean.sayHi("小白");
    }
}

8.切入表达式重用

代码实例
1.Car.java
java 复制代码
package com.sxs.spring.aop.joinpoint;

import org.springframework.stereotype.Component;

/**
 * @author 孙显圣
 * @version 1.0
 */
@Component
public class Car {
    public void run() {
        System.out.println("Car在运行!");
    }
}
2.Aspect02.java
java 复制代码
package com.sxs.spring.aop.joinpoint;

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

/**
 * @author 孙显圣
 * @version 1.0
 */
@Component
@org.aspectj.lang.annotation.Aspect
public class Aspect02 {
    //定义切点函数,实现切入表达式重用
    @Pointcut(value = "execution(* Car.run())") //设置切入表达式
    public void pointCut() {

    }

    /**
     * 前置通知
     *
     * @param joinPoint
     */
    @Before(value = "pointCut()")
    public void before(JoinPoint joinPoint) {
        System.out.println("前置通知");
    }

    /**
     * 返回通知获取结果
     *
     * @param joinPoint
     * @param res       参数名必须与returning的一致
     */
    @AfterReturning(value = "pointCut()", returning = "res")
    public void afterReturning(JoinPoint joinPoint, Object res) {
        System.out.println("返回结果为=" + res);
    }


    /**
     * 异常通知获取异常
     *
     * @param joinPoint
     * @param throwable 参数名必须与throwing一致
     */
    @AfterThrowing(value = "pointCut()", throwing = "throwable")
    public void afterThrowing(JoinPoint joinPoint, Throwable throwable) {
        System.out.println("异常通知获取异常:" + throwable);
    }

    /**
     * 后置通知
     * @param joinPoint
     */
    @After(value = "pointCut()")
    public void after(JoinPoint joinPoint) {
        System.out.println("后置通知");
    }
}
3.beans06.xml
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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--扫描普通注解-->
    <context:component-scan base-package="com.sxs.spring.aop.joinpoint"/>
<!--开启基于aop的注解功能-->
    <aop:aspectj-autoproxy/>
</beans>
4.测试
java 复制代码
package com.sxs.spring.aop.joinpoint;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class test {
    public static void main(String[] args) {
        //获取针对父类的代理对象
        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans06.xml");
        Car bean = ioc.getBean(Car.class);
        bean.run();
    }
}

9.AOP多切面优先级问题

解释
  1. 多个切面同时切一个方法
  2. 可以给切面类配置Order注解,数值越小,前置通知先执行
  3. 执行完前置通知之后执行目标方法
  4. 然后按照相反的顺序执行多个切面的返回通知、异常通知、最终通知

10.根据xml配置AOP

代码实例
1.UsbInterface.java
java 复制代码
package com.sxs.spring.aop.xml;

/**
 * @author 孙显圣
 * @version 1.0
 */
public interface UsbInterface {
    public void work();
}
2.Camera.java
java 复制代码
package com.sxs.spring.aop.xml;


/**
 * @author 孙显圣
 * @version 1.0
 */
public class Camera implements UsbInterface {
    @Override
    public void work() {
        System.out.println("相机正在工作。。。。。。");
    }
}
3.Aspect.java
java 复制代码
package com.sxs.spring.aop.xml;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class Aspect {
    /**
     * @param joinPoint 保存了要切入的方法的信息
     * @Before 前置通知
     * execution(。。。) 切入表达式,表明要切入的方法,格式:访问修饰符+返回类型 全类名 方法名(参数类型)
     */
    public void before(JoinPoint joinPoint) {
        //获取方法签名
        Signature signature = joinPoint.getSignature();
        System.out.println("方法执行开始-日志-方法名-" + signature.getName()
                + "-参数" + Arrays.asList(joinPoint.getArgs()));
    }

    /**
     * @param joinPoint 保存了要切入的方法的信息
     * @AfterReturning 返回通知
     */
    public void afterReturning(JoinPoint joinPoint, Object res) {
        Signature signature = joinPoint.getSignature();
        System.out.println("方法执行正常结束-日志-方法名-" + signature.getName()
        );
    }

    /**
     * @param joinPoint
     * @AfterThrowing 异常通知
     */
    public void throwing(JoinPoint joinPoint, Throwable throwable) {
        Signature signature = joinPoint.getSignature();
        System.out.println("方法出现异常-日志-方法名-" + signature.getName()
        );
    }

    /**
     * @param joinPoint
     * @After 后置通知
     */
    public void after(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        System.out.println("方法最终执行完毕-日志-方法名-" + signature.getName()
        );
    }}
4.beans07.xml
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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--创建被切入的接口对象-->
    <bean class="com.sxs.spring.aop.xml.Camera" id="camera"/>
    <!--配置切面对象-->
    <bean class="com.sxs.spring.aop.xml.Aspect" id="aspect"/>
    <!--配置AOP-->
    <aop:config>
        <!--配置切点-->
        <aop:pointcut id="poingCut" expression="execution(public void work())"/>
        <!--配置切面-->
        <aop:aspect ref="aspect" order="10">
            <!--前置通知-->
            <aop:before method="before" pointcut-ref="poingCut"/>
            <!--返回通知-->
            <aop:after-returning method="afterReturning" pointcut-ref="poingCut" returning="res"/>
            <!--异常通知-->
            <aop:after-throwing method="throwing" pointcut-ref="poingCut" throwing="throwable"/>
            <!--后置通知-->
            <aop:after method="after" pointcut-ref="poingCut"/>
        </aop:aspect>
    </aop:config>
</beans>
5.测试
java 复制代码
package com.sxs.spring.aop.xml;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class Test {
    public static void main(String[] args) {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans07.xml");
        //获得针对接口的代理对象
        UsbInterface bean = ioc.getBean(UsbInterface.class);
        bean.work();
    }
}

11.课后练习

1.注解实现
1.Cal.java
java 复制代码
package com.sxs.spring.aop.homework02;

/**
 * @author 孙显圣
 * @version 1.0
 */
public interface Cal {
    public void cal1(int n);
    public void cal2(int n);
}
2.CalImpl.java
java 复制代码
package com.sxs.spring.aop.homework02;

import org.springframework.stereotype.Component;

/**
 * @author 孙显圣
 * @version 1.0
 */
@Component
public class CalImpl implements Cal{
    /**
     * 计算1到n的和
     * @param n
     */
    @Override
    public void cal1(int n) {
        int sum = 0;
        for (int i = 1; i <= n; i++) {
            sum += i;
        }
        System.out.println("1到n的和=" + sum);
    }

    /**
     * 计算1乘到n
     * @param n
     */
    @Override
    public void cal2(int n) {
        int accumulate = 1;
        for (int i = 1; i <= n; i++) {
            accumulate *= i;
        }
        System.out.println("1到n的积=" + accumulate);
    }
}
3.Aspect_ann.java
java 复制代码
package com.sxs.spring.aop.homework02;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;


/**
 * @author 孙显圣
 * @version 1.0
 */
@Component
@Aspect
public class Aspect_ann {
    //切入表达式重用
    @Pointcut(value = "execution(* CalImpl.*(..))")
    public void pointCut() {

    }

    //前置通知
    @Before(value = "pointCut()")
    public void before(JoinPoint joinPoint) {
        //获取目前的毫秒数
        long start = System.currentTimeMillis();
        //获取函数名
        String name = joinPoint.getSignature().getName();
        System.out.println(name + "开始时间=" + start);
    }

    //返回通知
    @AfterReturning(value = "pointCut()")
    public void afterReturning(JoinPoint joinPoint) {
        //获取目前的毫秒数
        long end = System.currentTimeMillis();
        //获取函数名
        String name = joinPoint.getSignature().getName();
        System.out.println(name + "结束=" + end);
    }
}
4.beans06.xml
java 复制代码
<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--扫描普通注解-->
    <context:component-scan base-package="com.sxs.spring.aop.homework02"/>

<!--开启基于aop的注解功能-->
    <aop:aspectj-autoproxy/>
</beans>
5.测试
java 复制代码
package com.sxs.spring.aop.homework02;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class Test_ann {
    public static void main(String[] args) {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans06.xml");
        Cal bean = ioc.getBean(Cal.class);
        bean.cal1(5);
        System.out.println("===========================");
        bean.cal2(5);
    }
}
2.xml实现
1.Cal.java
java 复制代码
package com.sxs.spring.aop.homework03;

/**
 * @author 孙显圣
 * @version 1.0
 */
public interface Cal {
    public void cal1(int n);
    public void cal2(int n);
}
2.CalImpl.java
java 复制代码
package com.sxs.spring.aop.homework03;


/**
 * @author 孙显圣
 * @version 1.0
 */
public class CalImpl implements Cal {
    /**
     * 计算1到n的和
     * @param n
     */
    @Override
    public void cal1(int n) {
        int sum = 0;
        for (int i = 1; i <= n; i++) {
            sum += i;
        }
        System.out.println("1到n的和=" + sum);
    }

    /**
     * 计算1乘到n
     * @param n
     */
    @Override
    public void cal2(int n) {
        int accumulate = 1;
        for (int i = 1; i <= n; i++) {
            accumulate *= i;
        }
        System.out.println("1到n的积=" + accumulate);
    }
}
3.Aspect_xml.java
java 复制代码
package com.sxs.spring.aop.homework03;

import org.aspectj.lang.JoinPoint;


/**
 * @author 孙显圣
 * @version 1.0
 */
public class Aspect_xml {

    //前置通知
    public void before(JoinPoint joinPoint) {
        //获取目前的毫秒数
        long start = System.currentTimeMillis();
        //获取函数名
        String name = joinPoint.getSignature().getName();
        System.out.println(name + "开始时间=" + start);
    }

    //返回通知
    public void afterReturning(JoinPoint joinPoint) {
        //获取目前的毫秒数
        long end = System.currentTimeMillis();
        //获取函数名
        String name = joinPoint.getSignature().getName();
        System.out.println(name + "结束=" + end);
    }
}
4.beans08.xml
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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--反射创建实现类bean对象-->
    <bean class="com.sxs.spring.aop.homework03.CalImpl" id="calImpl"/>
    <!--反射创建切面类bean对象-->
    <bean class="com.sxs.spring.aop.homework03.Aspect_xml" id="aspect_xml"/>
    <!--配置aop-->
    <aop:config>
        <!--配置切点-->
        <aop:pointcut id="pointCut" expression="execution(* com.sxs.spring.aop.homework03.CalImpl.*(..))"/>
        <!--配置切面-->
        <aop:aspect ref="aspect_xml" id="aspect" order="10">
            <aop:before method="before" pointcut-ref="pointCut"/>
            <aop:after-returning method="afterReturning" pointcut-ref="pointCut"/>
        </aop:aspect>
    </aop:config>
</beans>
5.测试
java 复制代码
package com.sxs.spring.aop.homework03;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 孙显圣
 * @version 1.0
 */
public class Test_xml {
    public static void main(String[] args) {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans08.xml");
        //获取针对接口的代理对象
        Cal proxy = ioc.getBean("calImpl", Cal.class);
        proxy.cal1(100);
        System.out.println("=========================");
        proxy.cal2(5);
    }
}
相关推荐
Neoest9 分钟前
【EasyExcel 填坑日记】“Syntax error on token )“: 一次编译错误在逃 Runtime 的灵异事件
java·eclipse·编辑器
自在极意功。11 分钟前
Web开发中的分层解耦
java·microsoft·web开发·解耦
是一个Bug13 分钟前
ConcurrentHashMap的安全机制详解
java·jvm·安全
断剑zou天涯16 分钟前
【算法笔记】bfprt算法
java·笔记·算法
番石榴AI19 分钟前
java版的ocr推荐引擎——JiaJiaOCR 2.0重磅升级!纯Java CPU推理,新增手写OCR与表格识别
java·python·ocr
码事漫谈1 小时前
VSCode CMake Tools 功能解析、流程与最佳实践介绍
后端
鸽鸽程序猿1 小时前
【项目】【抽奖系统】抽奖
java·spring
火云牌神1 小时前
本地大模型编程实战(38)实现一个通用的大模型客户端
人工智能·后端
码事漫谈1 小时前
从C++/MFC到CEF与TypeScript的桌面架构演进
后端
GoogleDocs2 小时前
基于[api-football]数据学习示例
java·学习