• Spring之aop


    哈喽铁子们今天分享Spring之aop 先看目录

    目录

    1,AOP的概念(即面向切面编程)    1.1   目标(Target)           

    1.2   通知(Advice)

        1.3   代理(Proxy ) 

        1.4   切入点(Pointcut)

        1.5   适配器(Advisor)

        1.6   连接点(Joinpoint)

    2.前置通知

    三、后置通知

    四、环绕通知

    五、异常通知

    六、过滤通知(适配器)


    1,AOP的概念(即面向切面编程)
        1.1   目标(Target)
               

        被通知(被代理)的对象

     

    1.2   通知(Advice)


                    在某个特定的连接点上执行的动作,同时Advice也是程序代码的具体实现,例如一个实现日志记录的代码(通知有些书上也称为处理)

        1.3   代理(Proxy ) 


                  将通知应用到目标对象后创建的对象(代理=目标+通知),只有代理对象才有AOP功能,而AOP的代码是写在通知的方法里面的

        1.4   切入点(Pointcut)


                    多个连接点的集合,定义了通知应该应用到那些连接点。  (也将Pointcut理解成一个条件 ,此条件决定了容器在什么情况下将通知和目标组合成代理返回给外部程序)

        1.5   适配器(Advisor)


                    适配器=通知(Advice)+切入点(Pointcut)

        1.6   连接点(Joinpoint)


                    程序执行过程中明确的点,如方法的调用,或者异常的抛出.


    BookBiz.java:

    1. package com.tsq.aop.biz;
    2. public interface BookBiz {
    3. // 购书
    4. public boolean buy(String userName, String bookName, Double price);
    5. // 发表书评
    6. public void comment(String userName, String comments);
    7. }

     BookBizImpl.java:

    1. package com.tsq.aop.biz.impl;
    2. import com.tsq.aop.biz.BookBiz;
    3. import com.tsq.aop.exception.PriceException;
    4. public class BookBizImpl implements BookBiz {
    5. public BookBizImpl() {
    6. super();
    7. }
    8. public boolean buy(String userName, String bookName, Double price) {
    9. // 通过控制台的输出方式模拟购书
    10. if (null == price || price <= 0) {
    11. throw new PriceException("book price exception");
    12. }
    13. //logDao.add->sout("买书相关日志")
    14. System.out.println(userName + " buy " + bookName + ", spend " + price);
    15. return true;
    16. }
    17. public void comment(String userName, String comments) {
    18. // 通过控制台的输出方式模拟发表书评
    19. System.out.println(userName + " say:" + comments);
    20. //System.out.println("买书返利");
    21. }
    22. }

    PriceException.java:

    1. package com.tsq.aop.exception;
    2. public class PriceException extends RuntimeException {
    3. public PriceException() {
    4. super();
    5. }
    6. public PriceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
    7. super(message, cause, enableSuppression, writableStackTrace);
    8. }
    9. public PriceException(String message, Throwable cause) {
    10. super(message, cause);
    11. }
    12. public PriceException(String message) {
    13. super(message);
    14. }
    15. public PriceException(Throwable cause) {
    16. super(cause);
    17. }
    18. }

    2.前置通知

           (org.springframework.aop.MethodBeforeAdvice):在连接点之前执行的通知()
    案例:在购书系统当中使用AOP方式实现日志系统

    MyMethodBeforeAdvice.java

    1. package com.tsq.aop.advice;
    2. import java.lang.reflect.Method;
    3. import java.util.Arrays;
    4. import org.springframework.aop.MethodBeforeAdvice;
    5. public class MyMethodBeforeAdvice implements MethodBeforeAdvice{
    6. @Override
    7. public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
    8. //目标对象的类名
    9. String clzname = arg2.getClass().getName();
    10. //当前调用的方法是
    11. String methodName = arg0.getName();
    12. //当前调用方法所传递参数
    13. String args = Arrays.toString(arg1);
    14. System.out.println("【系统日志】:"+clzname+"."+methodName+"被调用,传递的参数"+args);
    15. }
    16. }

    spring-context.xml

    1. "bookBiz" class="com.tsq.biz.impl.BookBizImpl">
    2. "MyBefore" class="com.cxy.aop.advice.MyMethodBeforeAdvice">

    测试类

    1. package com.tsq.aop.demo;
    2. import org.springframework.context.support.ClassPathXmlApplicationContext;
    3. import com.tsq.biz.BookBiz;
    4. public class Demo1 {
    5. public static void main(String[] args) {
    6. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml");
    7. BookBiz bean = (BookBiz)context.getBean("bookBiz");
    8. bean.buy("aa", "tsq", 0.1d);
    9. bean.comment("aa", "cc");
    10. }
    11. }

    三、后置通知


    (org.springframework.aop.AfterReturningAdvice):在连接点正常完成后执行的通知
       案例:在线购书系统中,要求不修改BookBizImpl代码的情况下增加如下功能:对买书的用户进行返利:每买本书返利3元。(后置通知)

    MyAfterReturningAdvice .java

    1. package com.tsq.aop.advice;
    2. import java.lang.reflect.Method;
    3. import java.util.Arrays;
    4. import org.springframework.aop.AfterReturningAdvice;
    5. public class MyAfterReturningAdvice implements AfterReturningAdvice {
    6. public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
    7. String targetName = target.getClass().getName();
    8. String methodName = method.getName();
    9. String params = Arrays.toString(args);
    10. String msg = "【返利通知:返利3元】:正在调用" + targetName + "." + methodName + ",携带的参数:" + params + ";目标对象所调用的方法的返回值:"
    11. + returnValue;
    12. System.out.println(msg);
    13. }
    14. }

    Spring-context.xml 
            

    1. <bean name="MyAfter" class="com.tsq.aop.advice.MyAfterReturningAdvice">bean>

    四、环绕通知


    (org.aopalliance.intercept.MethodInterceptor):包围一个连接点的通知,最大特点是可以修改返回值,由于它在方法前后都加入了自己的逻辑代码,因此功能异常强大。
                 它通过MethodInvocation.proceed()来调用目标方法(甚至可以不调用,这样目标方法就不会执行)
       案例:修改日志系统不光要输出参数,还要输出返回值(环绕通知)
        MyMethodInterceptor.

    1. package com.tsq.aop.advice;
    2. import java.lang.reflect.Method;
    3. import java.util.Arrays;
    4. import org.aopalliance.intercept.MethodInterceptor;
    5. import org.aopalliance.intercept.MethodInvocation;
    6. public class MyMethodInterceptor implements MethodInterceptor {
    7. public Object invoke(MethodInvocation invocation) throws Throwable {
    8. Object target = invocation.getThis();
    9. Method method = invocation.getMethod();
    10. Object[] args = invocation.getArguments();
    11. String targetName = target.getClass().getName();
    12. String methodName = method.getName();
    13. String params = Arrays.toString(args);
    14. String msg = "【环绕通知】:正在调用->" + targetName + "." + methodName + ",携带的参数:" + params;
    15. System.out.println(msg);
    16. Object returnValue = invocation.proceed();
    17. String msg2 = "【环绕通知】:目标对象所调用的方法的返回值:" + returnValue;
    18. System.out.println(msg2);
    19. return returnValue;
    20. }
    21. }

    五、异常通知

         org.springframework.aop.ThrowsAdvice:这个通知会在方法抛出异常退出时执行
      案例: 书本价格为负数时抛出一个异常,通过异常通知取消此订单

    1. package com.tsq.aop.advice;
    2. import org.springframework.aop.ThrowsAdvice;
    3. import com.tsq.aop.exception.PriceException;
    4. public class MyThrowsAdvice implements ThrowsAdvice {
    5. public void afterThrowing(PriceException ex ) {
    6. System.out.println("价格输入错误,购买失败,请重新购买");
    7. }
    8. }

    spring-context.xml

    1. <bean name="MyException" class="com.tsq.aop.advice.MyThrowsAdvice">bean>

    六、过滤通知(适配器)

    org.springframework.aop.support.RegexpMethodPointcutAdvisor: 处理买书返利的bug 

    适配器=通知(Advice)+切入点(Pointcut)

     案例:通过适配器解决发书评时也返利的问题

    1. "org.springframework.aop.support.RegexpMethodPointcutAdvisor"
    2. id="MyAfter2">
    3. "advice" ref="MyAfter">
    4. "patterns">
    5. .*buy

    代理工厂 

    1. "org.springframework.aop.framework.ProxyFactoryBean"
    2. id="proxyFactoryBean">
    3. "target" ref="bookBiz">
    4. "proxyInterfaces">
    5. com.tsq.aop.biz.IBookBiz
    6. "interceptorNames">
    7. MyBefore
    8. MyAfter
    9. MyFilterAdvice
    10. MyException

    好了铁子们今天Spring之aop分享结束了

  • 相关阅读:
    Ruby语言:打造高性能Web应用程序
    区间修改,区间查询(线段树)
    Vue-3.4Vuex
    【详细介绍下PostgreSQL】
    An动画优化之补间形状与传统补间的优化
    阈值与平滑处理
    Jmeter保存报错Couldn‘t save test plan to file
    nginx.3——local的优先级和匹配方式
    【Unity Shader】屏幕后处理3.0:均值模糊和高斯模糊
    C语言 深度探究C语言中的预处理器
  • 原文地址:https://blog.csdn.net/weixin_65565181/article/details/126224282