spring boot(整理上课内容)---03

Spring中的可插拔组件技术(低耦合高扩展)

Spring AOP

 

1.Spring中的可插拔组件技术

 

2.Spring AOP

Spring AOP – Aspect Oriented Programming 面向切面编程  

AOP的做法是将通用的、与业务无关的功能抽象封装为切面类  

切面可配置在目标方法的执行前、后运行,真正做到即插即用  

可以在不修改源码的情况下对程序行为进行扩展  

应用场景:可用于日志记录、性能统计、权限管理等

 

3.几个关键概念

4.Spring AOP

5.Pointcut 切点表达式

6.JoinPoint的核心方法

7.五种通知类型

8.在 pom.xml 中引入 AOP 依赖

<!-- aop依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
            <version>2.3.10.RELEASE</version>
        </dependency>

 

9.给controller包中的类添加切面类

package com.example.mall.aspect;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
//如果不想要这个扩展功能就把@Component @Aspect注解注释掉就好了(可插拔)
@Component //标注为组件,可被实例化
@Aspect //标注为切面
public class ControllerAspect {
    private Logger logger = LoggerFactory.getLogger(ControllerAspect.class);

    //切入点execution表达式, 这里表示切入点为controller包下的所有方法
//    (第一个* :返回值类型任意类型   com.example.mall.controller.*.*(..)  :这个包中的所有类的所有方法  )
    @Pointcut("execution(public * com.example.mall.controller.*.*(..))")
    public void pointcut(){

    }
    //这是一个前置通知,该方法在目标方法执行之前执行
    @Before(value = "pointcut()")
    public void doBefore(JoinPoint joinPoint){
        //收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //请求方法
        String requestMethod = request.getMethod();
        //请求url
        String url = request.getRequestURL().toString();
        //请求接口的名称
        String apiName = joinPoint.getTarget().getClass().getName()  + "." +
                joinPoint.getSignature().getName();
        //请求中的参数,参数可能有多个
        String args = Arrays.toString(joinPoint.getArgs());
        logger.info("【请求方法】:{}, 【请求URL】:{}, 【请求接口方法】:{}, 【请求参数】:{}", requestMethod, url, apiName, args);
    }

    //这是一个返回通知,在该方法中可以获取目标方法的返回值
    @AfterReturning(value = "pointcut()", returning = "res")
    public void doAfterReturning(Object res){
        try {
            //把返回的对象转化为字符串
            String resString = new ObjectMapper().writeValueAsString(res);
            logger.info("【方法返回数据】:{}", resString);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

10.给service包添加切面类(计算本类的执行时间)

package com.example.mall.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class ServiceAspect {
    private Logger logger = LoggerFactory.getLogger(ServiceAspect.class);

    @Pointcut("execution(public * com.example.mall.service.*.*(..))")
    public void pointcut() {

    }

    // 环绕通知
    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        // 记录开始时间
        long startTime = System.currentTimeMillis();
        //目标方法执行,res保存目标方法的返回值
        Object res = joinPoint.proceed();
        logger.info("【服务层方法】: {}----【执行时间】{} 毫秒",
                joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName(),
                System.currentTimeMillis() - startTime
        );
        return res;
    }
}

11.控制台输出效果

"C:\Program Files\Java\jdk1.8.0_144\bin\java.exe" -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2021.1.1\lib\idea_rt.jar=53113:D:\Program Files\JetBrains\IntelliJ IDEA 2021.1.1\bin" -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dfile.encoding=GBK -classpath "C:\Program Files\Java\jdk1.8.0_144\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar;G:\spring-boot课堂作业\第三节课\mall\target\classes;C:\Users\DELL\.m2\repository\org\springframework\boot\spring-boot-starter-web\2.4.5\spring-boot-starter-web-2.4.5.jar;C:\Users\DELL\.m2\repository\org\springframework\boot\spring-boot-starter\2.4.5\spring-boot-starter-2.4.5.jar;C:\Users\DELL\.m2\repository\org\springframework\boot\spring-boot\2.4.5\spring-boot-2.4.5.jar;C:\Users\DELL\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.4.5\spring-boot-autoconfigure-2.4.5.jar;C:\Users\DELL\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.4.5\spring-boot-starter-logging-2.4.5.jar;C:\Users\DELL\.m2\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\Users\DELL\.m2\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\Users\DELL\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.13.3\log4j-to-slf4j-2.13.3.jar;C:\Users\DELL\.m2\repository\org\apache\logging\log4j\log4j-api\2.13.3\log4j-api-2.13.3.jar;C:\Users\DELL\.m2\repository\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;C:\Users\DELL\.m2\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;C:\Users\DELL\.m2\repository\org\yaml\snakeyaml\1.27\snakeyaml-1.27.jar;C:\Users\DELL\.m2\repository\org\springframework\boot\spring-boot-starter-json\2.4.5\spring-boot-starter-json-2.4.5.jar;C:\Users\DELL\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.11.4\jackson-databind-2.11.4.jar;C:\Users\DELL\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.11.4\jackson-annotations-2.11.4.jar;C:\Users\DELL\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.11.4\jackson-core-2.11.4.jar;C:\Users\DELL\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.11.4\jackson-datatype-jdk8-2.11.4.jar;C:\Users\DELL\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.11.4\jackson-datatype-jsr310-2.11.4.jar;C:\Users\DELL\.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.11.4\jackson-module-parameter-names-2.11.4.jar;C:\Users\DELL\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\2.4.5\spring-boot-starter-tomcat-2.4.5.jar;C:\Users\DELL\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.45\tomcat-embed-core-9.0.45.jar;C:\Users\DELL\.m2\repository\org\glassfish\jakarta.el\3.0.3\jakarta.el-3.0.3.jar;C:\Users\DELL\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.45\tomcat-embed-websocket-9.0.45.jar;C:\Users\DELL\.m2\repository\org\springframework\spring-web\5.3.6\spring-web-5.3.6.jar;C:\Users\DELL\.m2\repository\org\springframework\spring-beans\5.3.6\spring-beans-5.3.6.jar;C:\Users\DELL\.m2\repository\org\springframework\spring-webmvc\5.3.6\spring-webmvc-5.3.6.jar;C:\Users\DELL\.m2\repository\org\springframework\spring-context\5.3.6\spring-context-5.3.6.jar;C:\Users\DELL\.m2\repository\org\springframework\spring-expression\5.3.6\spring-expression-5.3.6.jar;C:\Users\DELL\.m2\repository\org\mybatis\spring\boot\mybatis-spring-boot-starter\2.1.4\mybatis-spring-boot-starter-2.1.4.jar;C:\Users\DELL\.m2\repository\org\springframework\boot\spring-boot-starter-jdbc\2.4.5\spring-boot-starter-jdbc-2.4.5.jar;C:\Users\DELL\.m2\repository\com\zaxxer\HikariCP\3.4.5\HikariCP-3.4.5.jar;C:\Users\DELL\.m2\repository\org\springframework\spring-jdbc\5.3.6\spring-jdbc-5.3.6.jar;C:\Users\DELL\.m2\repository\org\springframework\spring-tx\5.3.6\spring-tx-5.3.6.jar;C:\Users\DELL\.m2\repository\org\mybatis\spring\boot\mybatis-spring-boot-autoconfigure\2.1.4\mybatis-spring-boot-autoconfigure-2.1.4.jar;C:\Users\DELL\.m2\repository\org\mybatis\mybatis\3.5.6\mybatis-3.5.6.jar;C:\Users\DELL\.m2\repository\org\mybatis\mybatis-spring\2.0.6\mybatis-spring-2.0.6.jar;C:\Users\DELL\.m2\repository\mysql\mysql-connector-java\8.0.23\mysql-connector-java-8.0.23.jar;C:\Users\DELL\.m2\repository\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;C:\Users\DELL\.m2\repository\org\springframework\spring-core\5.3.6\spring-core-5.3.6.jar;C:\Users\DELL\.m2\repository\org\springframework\spring-jcl\5.3.6\spring-jcl-5.3.6.jar;C:\Users\DELL\.m2\repository\org\springframework\boot\spring-boot-starter-aop\2.3.10.RELEASE\spring-boot-starter-aop-2.3.10.RELEASE.jar;C:\Users\DELL\.m2\repository\org\springframework\spring-aop\5.3.6\spring-aop-5.3.6.jar;C:\Users\DELL\.m2\repository\org\aspectj\aspectjweaver\1.9.6\aspectjweaver-1.9.6.jar" com.example.mall.MallApplication

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.5)

2021-05-18 22:27:30.420 [main] INFO  com.example.mall.MallApplication - Starting MallApplication using Java 1.8.0_144 on DESKTOP-QLIMIR2 with PID 1396 (G:\spring-boot课堂作业\第三节课\mall\target\classes started by DELL in G:\spring-boot课堂作业\第三节课\mall) 
2021-05-18 22:27:30.426 [main] INFO  com.example.mall.MallApplication - No active profile set, falling back to default profiles: default 
2021-05-18 22:27:32.620 [main] INFO  o.s.boot.web.embedded.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http) 
2021-05-18 22:27:32.635 [main] INFO  org.apache.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8080"] 
2021-05-18 22:27:32.637 [main] INFO  org.apache.catalina.core.StandardService - Starting service [Tomcat] 
2021-05-18 22:27:32.637 [main] INFO  org.apache.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.45] 
2021-05-18 22:27:32.794 [main] INFO  o.a.c.core.ContainerBase.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext 
2021-05-18 22:27:32.795 [main] INFO  o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 2288 ms 
2021-05-18 22:27:34.063 [main] INFO  o.s.scheduling.concurrent.ThreadPoolTaskExecutor - Initializing ExecutorService 'applicationTaskExecutor' 
2021-05-18 22:27:34.811 [main] INFO  org.apache.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8080"] 
2021-05-18 22:27:34.856 [main] INFO  o.s.boot.web.embedded.tomcat.TomcatWebServer - Tomcat started on port(s): 8080 (http) with context path '' 
2021-05-18 22:27:34.871 [main] INFO  com.example.mall.MallApplication - Started MallApplication in 5.332 seconds (JVM running for 8.421) 
2021-05-18 22:28:31.626 [http-nio-8080-exec-1] INFO  o.a.c.core.ContainerBase.[Tomcat].[localhost].[/] - Initializing Spring DispatcherServlet 'dispatcherServlet' 
2021-05-18 22:28:31.626 [http-nio-8080-exec-1] INFO  org.springframework.web.servlet.DispatcherServlet - Initializing Servlet 'dispatcherServlet' 
2021-05-18 22:28:31.629 [http-nio-8080-exec-1] INFO  org.springframework.web.servlet.DispatcherServlet - Completed initialization in 3 ms 
2021-05-18 22:28:31.740 [http-nio-8080-exec-1] INFO  com.example.mall.aspect.ControllerAspect - 【请求方法】:GET, 【请求URL】:http://localhost:8080/user/1, 【请求接口方法】:com.example.mall.controller.UserController.getUser, 【请求参数】:[1] 
2021-05-18 22:28:31.827 [http-nio-8080-exec-1] INFO  com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting... 
2021-05-18 22:28:32.587 [http-nio-8080-exec-1] INFO  com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed. 
2021-05-18 22:28:32.754 [http-nio-8080-exec-1] INFO  com.example.mall.aspect.ServiceAspect - 【服务层方法】: com.example.mall.service.UserService.getUserByPK----【执行时间】991 毫秒 
2021-05-18 22:28:32.884 [http-nio-8080-exec-1] INFO  com.example.mall.aspect.ControllerAspect - 【方法返回数据】:{"id":1,"username":"1","password":"1","personalizedSignature":"3","role":1,"createTime":1576435053000,"updateTime":1581244872000} 
2021-05-18 22:29:19.047 [http-nio-8080-exec-2] INFO  com.example.mall.aspect.ControllerAspect - 【请求方法】:GET, 【请求URL】:http://localhost:8080/user/1, 【请求接口方法】:com.example.mall.controller.UserController.getUser, 【请求参数】:[1] 
2021-05-18 22:29:19.054 [http-nio-8080-exec-2] INFO  com.example.mall.aspect.ServiceAspect - 【服务层方法】: com.example.mall.service.UserService.getUserByPK----【执行时间】7 毫秒 
2021-05-18 22:29:19.069 [http-nio-8080-exec-2] INFO  com.example.mall.aspect.ControllerAspect - 【方法返回数据】:{"id":1,"username":"1","password":"1","personalizedSignature":"3","role":1,"createTime":1576435053000,"updateTime":1581244872000} 
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值