SSM复习总结-Spring AOP

SSM and SpringBoot(复习) 用于springboot的复习阶段 阅读详情

代理设计模式

代理设计模式的优点:将通用性的工作都交给代理对象完成,被代理对象只需关乎自己的核心业务。

静态代理

静态代理,代理类只能够为特定的类生产代理对象,不能代理任意类

在这里插入图片描述
使用代理的好处

  1. 被代理类中只用关注核心业务的实现,将通用的管理型逻辑(事务管理、日志管理)和业务逻辑分离
  2. 将通用的代码放在代理类中实现,提供了代码的复用性
  3. 通过在代理类添加业务逻辑,实现对原有业务逻辑的扩展(增强)

动态代理

动态代理,几乎可以为所有的类产生代理对象
动态代理的实现方式有两种:
JDK动态代理
CGLib动态代理

JDK动态代理

package com.qfedu.dao;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author Helen
 * @version 1.0
 * @createTime 2022/1/9 17:36
 * @Description JDK动态代理:是通过被代理对象实现的接口产生其代理对象的
 * 1. 创建一个类,实现InvocationHandler接口,实现invoke方法
 * 2.在类中定义一个Object类型的变量,并提供这个变量的有参构造器,用于将被代理对象传递进来
 * 3.创建getProxy方法,用于创建并返回代理对象
 */
public class JdkDynamicProxy implements InvocationHandler {
    /**
     * 被代理对象
     */
    private Object object;

    public JdkDynamicProxy(Object object) {
        this.object = object;
    }

    /**
     * 产生代理对象,返回代理对象
     */
    public Object getProxy() {
        /**1.获取被代理对象的类加载器*/
        ClassLoader classLoader = object.getClass().getClassLoader();
        /**2.获取被代理对象的类实现的接口*/
        Class<?>[] interfaces = object.getClass().getInterfaces();
        /**3.产生代理对象(通过被代理对象的类加载器及实现的接口)
         * 第一个参数:被代理对象的类加载器
         * 第二个参数:被代理对象实现的接口
         * 第三个参数:使用产生代理对象调用方法时,用于拦截方法执行的处理器
         * */
        Object obj = Proxy.newProxyInstance(classLoader, interfaces, this);
        return obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("----------------拦截");
        begin();
        /**执行method方法(传递进来的方法)*/
        Object obj = method.invoke(object,args);
//        System.out.println(method);
        commit();
        return obj;
    }

    public void begin() {
        System.out.println("-----开启事务");
    }

    public void commit() {
        System.out.println("-----提交事务");
    }
}

测试代码

package com.qfedu.dao;

/**
 * @author Helen
 * @version 1.0
 * @createTime 2022/1/9 17:46
 * @Description
 */
public class JdkDynamicProxyTest{
    public static void main(String[] args) {
        /**被代理对象*/
        BookDAOImpl bookDAO=new BookDAOImpl();
        StudentDAOImpl studentDAO=new StudentDAOImpl();
        /**创建动态代理对象,并将被代理对象传递到代理类中赋值给obj*/
        JdkDynamicProxy jdkDynamicProxy=new JdkDynamicProxy(bookDAO);
        /**proxy就是产生的代理对象:产生的代理对象可以强转成被代理对象实现的接口类型*/
        GeneralDAO proxy=(GeneralDAO)jdkDynamicProxy.getProxy();
        /**使用代理对象调用方法,不会直接进入被代理类,而是进入到创建代理对象时指定的InvocationHandler类中的invoke方法,
         *调用的方法作为一个Method参数,传递给了invoke方法
         */
        proxy.delete();
    }
}

测试结果
在这里插入图片描述

CGLib动态代理

由于JDK动态代理是通过被代理类实现的接口来创建代理对象的,因此JDK动态代理只能实现了接口的类的对象。如果一个类没有实现任何接口,该如何产生代理对象呢?
CGLib动态代理,是通过创建被代理类的子类来创建代理对象的,因此即使没有实现任何接口的类也可以通过CGLib产生代理对象
CGLib动态代理不能为final类创建代理对象

  • 添加CGLib的依赖
 <!-- https://mvnrepository.com/artifact/cglib/cglib -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
        </dependency>
package com.qfedu.dao;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @author Helen
 * @version 1.0
 * @createTime 2022/1/9 20:52
 * @Description
 * 1.添加cglib依赖
 * 2. 创建一个类,实现MethodInterceptor,同时实现接口intercept方法
 * 3. 在类中定义一个Object类型的变量,并提供这个变量的有参构造器,用于传递被代理对象
 * 4. 定义getProxy方法创建并返回代理对象(代理对象是通过创建被代理类的子类来创建的)
 */
public class CGLibDynamicProxy implements MethodInterceptor {
    private Object object;
    public CGLibDynamicProxy(Object object){
        this.object=object;
    }
    public Object getProxy(){
        Enhancer enhancer=new Enhancer();
        /**设置父类*/
        enhancer.setSuperclass(object.getClass());
        /***/
        enhancer.setCallback(this);
        return enhancer.create();
    }
    public void begin() {
        System.out.println("-----开启事务");
    }

    public void commit() {
        System.out.println("-----提交事务");
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib拦截");
        begin();
         /**通过反射调用被代理类的方法*/
        Object obj = method.invoke(object,objects);
        commit();
        return obj;
    }
}

测试

package com.qfedu.dao;

/**
 * @author Helen
 * @version 1.0
 * @createTime 2022/1/9 21:09
 * @Description
 */
public class CGLibDynamicProxyTest {
    public static void main(String[] args) {
        /**创建被代理对象*/
        BookDAOImpl bookDAO=new BookDAOImpl();
        /**通过cglib动态代理类创建代理对象*/
        CGLibDynamicProxy cgLibDynamicProxy=new CGLibDynamicProxy(bookDAO);
        /**代理对象实际上是被代理对象子类,因此代理对象可直接强转为被代理类类型*/
        BookDAOImpl obj= (BookDAOImpl) cgLibDynamicProxy.getProxy();
        /**使用对象调用方法,实际上并没有执行这个方法,而是执行了代理类中的intercept犯法,将当前调用的方法以及方法中的参数
         * 传递到intercept方法
         */
        obj.delete();
    }
}

在这里插入图片描述

Spring AOP

AOP概念

Aspect Oriented Programming面向切面编程,是一种利用“横切”的技术(底层实现就是动态代理),对原有的业务逻辑进行拦截,并且可以在这个拦截的横切面上添加特定的业务逻辑,对原有的业务进行增强。
基于动态实现在不改变原有业务的情况下

在这里插入图片描述

框架部署

框架依赖

 <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.19.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.19.RELEASE</version>
        </dependency>

创建Spring配置文件

  • 需要引入aop的命名空间
<?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">

    
</beans>

AOP-基于XML

在DAO的方法添加开启事务和提交事务的逻辑

创建一个类,定义要添加的业务逻辑

public class TxManager {
    public void begin(){
        System.out.println("------开启事务");
    }
    public void commit(){
        System.out.println("-----提交事务");
    }
}

配置aop

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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://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:annotation-config/>
    <context:component-scan base-package="com.qfedu"/>
    <aop:config>
        <!--声明切入点-->
        <aop:pointcut id="bookUpdate" expression="execution(* com.qfedu.dao.*.*(..))"/>
        <!--声明txManager为切面类-->
        <aop:aspect ref="txManager">
            <!--通知-->
            <aop:before method="begin" pointcut-ref="bookUpdate"/>
            <aop:after method="commit" pointcut-ref="bookUpdate"/>
        </aop:aspect>        
    </aop:config>
</beans>
package com.qfedu.utils;

import org.springframework.stereotype.Component;

/**
 * @author Helen
 * @version 1.0
 * @createTime 2022/1/9 22:42
 * @Description
 */
@Component
public class TxManager {
    public void begin(){
        System.out.println("------开启事务");
    }
    public void commit(){
        System.out.println("-----提交事务");
    }
}
package com.qfedu.dao;

import org.springframework.stereotype.Component;

/**
 * @author Helen
 * @version 1.0
 * @createTime 2022/1/9 16:43
 * @Description
 */
@Component(value = "bookDAO")
public class BookDAOImpl{
    public void insert() {
        System.out.println("insert book");
    }

    public void delete(int id) {
        System.out.println("delete book id = "+id);
    }

    public void update() {
        System.out.println("update book");
    }
}

测试代码

package com.qfedu.test;

import com.qfedu.dao.BookDAOImpl;
import com.qfedu.dao.StudentDAOImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author Helen
 * @version 1.0
 * @createTime 2022/1/9 22:33
 * @Description
 */
public class TestCase {
    public static void main(String[] args) {
        /**通过Spring容器获取BookDAOImpl的对象,并调用方法*/
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        BookDAOImpl bookDAO=context.getBean("bookDAO",BookDAOImpl.class);
        bookDAO.insert();
        bookDAO.delete(2);
    }
}

测试结果
在这里插入图片描述
AOP开发步骤

  1. 创建切面类,在切面类定义切点方法
  2. 将切面类配置给Spring容器
  3. 声明切入点
  4. 配置AOP的通知策略

切入点声明

各种切入点声明方式

例如定义切入点表达式execution (* com.qfedu.dao..*. *(..))
execution()是最常用的切点函数,其语法如下所示:
整个表达式可以分为五个部分:
1、execution(): 表达式主体。
2、第一个*号:表示返回类型, *号表示所有的类型。
3、包名:表示需要拦截的包名,后面的两个句点..表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。
4、第二个*号:表示类名,*号表示所有的类。
5、*(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数

 <aop:config>
        <!--使用aop:pointcut标签声明切入点:切入点可以是一个方法-->
        <aop:pointcut id="bookUpdate" expression="execution(* com.qfedu.dao.*.*(..))"/>
        <!--BookDAOImpl类中所有无参数无返回值的方法-->
        <aop:pointcut id="book_pc1" expression="execution(void com.qfedu.dao.BookDAOImpl.*())"/>
        <!--BookDAOImpl类中所有无返回值的方法-->
        <aop:pointcut id="book_pc2" expression="execution(void com.qfedu.dao.BookDAOImpl.*(..))"/>
        <!--BookDAOImpl类中所有无参数的方法-->
        <aop:pointcut id="book_p3" expression="execution(* com.qfedu.dao.BookDAOImpl.*())"/>
        <!--BookDAOImpl类中所有方法-->
        <aop:pointcut id="book_p4" expression="execution(* com.qfedu.dao.BookDAOImpl.*(..))"/>
        <!--dao包中所有类中的所有方法-->
        <aop:pointcut id="p5" expression="execution(* com.qfedu.dao.*.*(..))"/>
        <!--dao包中所有类中的insert方法-->
        <aop:pointcut id="p6" expression="execution(* com.qfedu.dao.*.insert(..))"/>
        <!--dao包中所有类中的方法-->
        <aop:pointcut id="p7" expression="execution(* *(..))"/>
        <!--声明txManager为切面类-->
        <aop:aspect ref="txManager">
            <!--通知-->
            <aop:before method="begin" pointcut-ref="p7"/>
            <aop:after method="commit" pointcut-ref="p7"/>
        </aop:aspect>
        <aop:aspect ref="logManager">
<!--            <aop:before method="printLog" pointcut-ref=""/>-->
        </aop:aspect>
    </aop:config>

AOP使用注意事项

 /**通过Spring容器获取BookDAOImpl的对象,并调用方法*/
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        BookDAOImpl bookDAO=context.getBean("bookDAO",BookDAOImpl.class);
        bookDAO.insert();
        bookDAO.delete(2);
        /**如果要使用Spring aop面向切面编程,调用切入点方法的对象必须通过Spring容器获取
         * 如果一个类中的方法被声明为切入点并且织入切点之后,通过Spring容器获取对象,实则获取到的是一个代理对象
         * 如果一个类中的方法没有被声明为切入点,通过Spring容器获取的就是这个类真实创建的对象
         * */
        BookService bookService=context.getBean("bookService",BookService.class);
        bookService.addBook();

AOP通知策略

AOP通知策略:就是声明将切面类中的切点方法如何织入到切入点

  • before
  • after
  • after-throwing
  • after-returning
  • around
    定义切面类
package com.qfedu.utils;

import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;

/**
 * @author Helen
 * @version 1.0
 * @createTime 2022/1/12 18:04
 * @Description
 */
@Component
public class MyAspect {
    public void method1(){
        System.out.println("method1");
    }
    public void method2(){
        System.out.println("method2");
    }
    public void method3(){
        System.out.println("method3");
    }
    public void method4(){
        System.out.println("method4");
    }
    /**
     *环绕通知的切点方法必须遵守如下规则:
     *  1. 必须带有一个ProceedingJoinPoint类型的参数,
     *  2. 必须有Object类型的返回值
     *  3.在前后增强的业务逻辑之间执行 Object o=joinPoint.proceed();
     *  4. 方法最后返回o
     * */
    public Object method5(ProceedingJoinPoint joinPoint) throws Throwable {
        /**此行代码的执行,表示切入点代码的执行*/
        Object o=joinPoint.proceed();
        System.out.println("环绕通知");
        System.out.println("joinPoint="+joinPoint);
        System.out.println("o="+o);
        System.out.println("method5");
        return o;
    }
}

配置切面类

<?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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://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:annotation-config/>
    <context:component-scan base-package="com.qfedu"/>
    <aop:config>
        <!--dao包中所有类中的insert方法-->
        <aop:pointcut id="p6" expression="execution(* com.qfedu.dao.*.insert(..))"/>
        <!--声明txManager为切面类-->
        <aop:aspect ref="myAspect">
            <!--aop:before 前置通知,指定切入点之前-->
            <aop:before method="method1" pointcut-ref="p6"/>
            <!--aop:after 后置通知,指定切入点之后-->
            <aop:after method="method2" pointcut-ref="p6"/>
            <!--aop:after-throwing异常通知,切入点方法抛出异常之后-->
            <aop:after-throwing method="method3" pointcut-ref="p6"/>
            <!--after-returning:方法返回值返回之后,对于一个java方法而言,return 返回值
            也是方法的一部分,因此,“方法返回值返回之后”和“方法执行结束”是同一个时间点,所以,
            after和after-returning根据配置的顺序决定执行的顺序
            -->
            <aop:after-returning method="method4" pointcut-ref="p6"/>
            <aop:around method="method5" pointcut-ref="p6"/>
<!--            <aop:around method="method2" pointcut-ref="p6"/>-->
        </aop:aspect>
    </aop:config>
</beans>

测试

package com.qfedu.test;

import com.qfedu.dao.BookDAOImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author Helen
 * @version 1.0
 * @createTime 2022/1/12 18:11
 * @Description
 */
public class TestCase2 {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        BookDAOImpl bookDAO=context.getBean("bookDAO",BookDAOImpl.class);
        bookDAO.insert();
    }
}

测试结果
在这里插入图片描述

Spring AOP 注解配置

  1. 创建Maven工厂
  2. 添加Spring依赖(context,aspects)
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.19.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.19.RELEASE</version>
        </dependency>
    </dependencies>
  1. 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"
       xmlns:context="http://www.springframework.org/schema/context"
       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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>
    <context:component-scan base-package="com.qfedu"/>
    <!--基于注解配置的AOP代理-->
    <aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>
  1. AOP注解配置案例
package com.qfedu.dao;

import org.springframework.stereotype.Component;

/**
 * @author Helen
 * @version 1.0
 * @createTime 2022/1/12 19:33
 * @Description
 */
@Component(value = "userDAO")
public class UserDAOImpl {
    public void insert(){
        System.out.println("insert-------user");
    }
    public void delete(int id){
        System.out.println("delete id="+id);
    }
}
package com.qfedu.utils;

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

/**
 * @author Helen
 * @version 1.0
 * @createTime 2022/1/12 19:41
 * @Description 切面类
 */
@Component
@Aspect
public class TransactionManager {
    /**
     * 声明切入点
     * p1:切入点名称
     */
    @Pointcut("execution(* com.qfedu.dao.*.*(..))")
    public void p1(){

    }

    /**
     *@Before: 前置通知
     * begin:前置通知名称
     * p1():切入点方法
     */
    @Before("p1()")
    public void begin(){
        System.out.println("----开启事务");
    }

    /**
     * @After: 后置通知
     */
    @After("p1()")
    public void commit(){
        System.out.println("----提交");
    }

    /**
     * 环绕通知
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("p1()")
    public Object printExecuteTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long time1 = System.currentTimeMillis();
        Object o =joinPoint.proceed();
        System.out.println("joinPoint="+joinPoint);
        System.out.println(o);
        long time2=System.currentTimeMillis();
        System.out.println("time="+(time2-time1));
        return o;
    }
}

注意: 注解使用虽然方便,但是只能在源码上添加注解,因此我们的自定义类提倡使用注解配置,如果使用到第三方提供的类则需要通过xml配置形式完成配置。
测试代码

package com.qfedu.test;

import com.qfedu.dao.UserDAOImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author Helen
 * @version 1.0
 * @createTime 2022/1/12 19:34
 * @Description
 */
public class TestCase {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDAOImpl userDAO= context.getBean("userDAO", UserDAOImpl.class);
        userDAO.insert();
        userDAO.delete(2);
    }
}

测试结果
在这里插入图片描述

什么是AOP? AOP是一种面向切面的编程,是基于动态代理的,对原有代码毫无入侵性,把和主业务无关的事情,放到代码外面去做。所以当你下次发现某一行代码经常在你的Controller里出现,比如方法入口日志打印,那就要考虑使用AOP来精简你的代码了。 也可以用一句话去概括:在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。 AOP分为五种通知类型,分别是前置通知、正常返回通知、异... 阅读详情

相关推荐

大模型训练(1):流水线并行

Gpipe的方法是,在训练时计算和运用的是micro-batch里的均值和方差,但同时持续追踪全部mini-batch的移动平均和方差,以便在测试阶段进行使用。流水线并行的核心思想是:在模型并行的基础上,进一步引入数据并行的办法,即把原先的数据再划分成若干个更小的batch,分批送入GPU进行训练,算一部分就让下一个GPU动起来。从实验结果可知,在关掉NVlinks的情况下,Gpipe一样也能实现随着GPU数量的增加,训练速度也增加的效果。前文说过,随着模型的增加,每块GPU中存储的中间结果也会越大。

呆呆象呆呆的博客 1968

AOP(面向切面编程)全面解析

AOP(Aspect-Oriented Programming),即面向切面编程,是一种通过分离应用中的横切关注点(Cross-Cutting Concerns)来实现模块化的软件开发范式。AOP的核心思想是将某些通用功能(如日志、事务管理、异常处理等)从业务逻辑代码中剥离出来,形成独立的切面模块。AOP允许我们在不修改原始代码的情况下为程序添加额外的功能,从而实现代码的解耦和复用。通俗地说,AOP是通过切面来定义和隔离特定操作的编程方式,使得开发者可以在程序的不同部分“切入”这些操作。

hello.reader 7077

随机森林的可解释性分析(含python代码)

随机森林的“黑箱”特性逐渐凸显,这使得我们难以理解和解释模型内部的工作机制。对于许多应用场景而言,仅仅获得高准确率的预测结果是不够的;了解预测背后的逻辑同样重要,特别是在医疗诊断、金融风险评估等领域。因此,对随机森林进行可解释性分析变得尤为重要。

m0_59257547的博客 3847

1.什么是AOP?2. 为什么使用AOP 3.AOP应用场景4. AOP的结构 5.如何使用AOP5.1切面通知处理

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。AOP:它是面向切面编程的语言,它可以让你的业务代码和非业务代码进行隔离。

weixin_64636083的博客 1079

基于Android Studio的校园智能点餐系统开发实战(附完整源码与部署指南)

本文详细介绍了基于Android Studio开发校园智能点餐系统的完整流程,包括需求分析、环境搭建、数据库设计、客户端与后台功能实现。系统采用SSM框架和MySQL数据库,解决了校园食堂高峰期排队问题,提供高效的点餐体验。附完整源码与部署指南,助力开发者快速构建类似应用。

weixin_29015801的博客 558

【Android】汽车电源管理:深入解析CarPowerManager与Suspend To RAM的交互机制

本文深入解析了Android Automotive OS中CarPowerManager与Suspend To RAM(深度睡眠)的交互机制。详细阐述了从车辆发出睡眠请求,到CarPowerManagementService协调应用状态,最终通过内核进入低功耗睡眠的完整流程,并探讨了唤醒机制、开发者实践及功耗优化策略,为车机应用开发与系统优化提供关键指导。

weixin_28339967的博客 289

AOP是什么?

3、连接点【Joinpotint】

weixin_54877075的博客 7705

从无序到结构化:HAC框架如何用哈希网格重构3D高斯压缩范式 | ECCV2024技术解读

本文深入解读了ECCV 2024提出的HAC框架,它通过引入二值哈希网格为无序的3D高斯锚点建立空间结构,并利用上下文模型进行自适应量化,从而实现了对3D Gaussian Splatting模型的高效压缩。该方法将压缩范式从单纯削减数据转向智能理解数据关系,在保持高质量渲染的同时,显著提升了压缩率,为移动端部署和实时应用提供了新方案。

yolo5detector的博客 459

什么是AOP

笔记

jlcheerful的博客 1661

GJB软件需求规格说明-编制指南

《软件需求规格说明》是软件开发过程必不可少的文档,并且需要评审,也是后续鉴定试验的依据,因此,非常有必要认真对待此文档。 文档对于很多开发技术人员来说是一件非常头疼的事,虽然标准有要求,但是光看标准还是难以下笔。 本文将详细讲解如何按照GJB 438C的要求编写《软件需求规格说明》。 注:文中有背景颜色内容为标准内容,加粗部分为范例。斜体部分为解释。 全文1.3万字

Abel的博客 6349

复制幻灯片到另一个PPT编程

请确保将源PPT文件和目标PPT文件的文件名修改为你实际使用的文件名。运行上述代码后,目标PPT将包含源PPT中的所有幻灯片和形状。这里假设源PPT文件名为"source.pptx",目标PPT文件名为"target.pptx"。方法将每个幻灯片的布局添加到目标PPT中。是一个强大的库,可以用于创建、修改和操作PPT文件。要将一个PPT中的幻灯片复制到另一个PPT,可以使用Python的。这段代码遍历源PPT的每个幻灯片,并使用。步骤 3: 打开源PPT和目标PPT。这将保存修改后的目标PPT文件。

ByteSparkX的博客 1322

SSM基础专项复习6——Spring框架AOP(3)

什么是 AOP 的技术?在软件业,AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程。AOP 是一种编程范式,隶属于软工范畴,指导开发者如何组织程序结构。AOP 最早由 AOP 联盟的组织提出的,制定了一套规范,Spring 将AOP 思想引入到框架中,必须遵守 AOP 联盟的规范通过预编译方式或者运行期动态代理实现程序功能的统一维护的一种技术。

2301_78566776的博客 863

汽车UDS诊断之诊断会话控制服务(0x10)深度剖析

DiagnosticSessionControl就是诊断会话控制。 请求消息定义 A_Data类型 参数名称 Cvt 字节值 助记符 #1 诊断会话控制请求SID M 0x10 DSC #2 子功能=[诊断会话类型] M 0x00-0xFF LEV_DS_ ...

心骗小白话的博客 7418

小菜鸟 SSM框架之 Spring复习-04(AOP-AspectJ-上 )

Spring AOP 简介 什么是AOP AOP的全称是Aspect—Oriented Programing,即面向切面编程(也称面向方面编程)。他是面向对象编程(OOP)的一种扩充。 AOP采取横向抽取机制,将分散在各个方法中的重复代码提取出来,然后再程序编译或运行时再将这些代码应用到需要执行的地方。这种机制OOP是无法办到的,因为OOP只能实现父子关系的纵向的重用。虽然AOP是一种新的编程思想,但却不是OOP的替代品,只是OOP的延申和补充。 AOP的使用,可以使编程人员在编写业务逻辑使专心域核心业务的

菜鸟小黑的博客 275

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

小菜鸟 SSM框架之 Spring复习-04(AOP-AspectJ-中)

基于代理类的AOP实现 spring中的AOP代理默认就是使用JDK动态代理实现的。在spring中使用ProxyFactoryBean 是创建AOP代理的最基本的方式(需要导入aop 和aoplliance两个包) Spring 的通知类型 spring的通知按照是在目标类方法连接点的位置可分为一下五种: 通知类型 说明 (环绕通知) org.aopllance.intercept.MethodInterceptor 在目标方法执行前后实施增强,可用于日志和事务管理等功能 (前置通

菜鸟小黑的博客 199

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

小菜鸟 SSM框架之 Spring复习-04(AOP-AspectJ-下 )

AspectJ 开发 基于XML 的声明式 AspectJ 基于XML 的声明式 AspectJ 是通过 xml 文件来定义切面、切入点、通知的。所有的切面、切入点、通知必须定义在<aop:config>元素内。 Spring配置文件中元素中可以包含多个<aop:config>元素, 注意:在标签<aop:config> 里面配置时,要按照<aop:pointcut>、<aop:advisor>、<aop:aspect>顺序来配置

菜鸟小黑的博客 257

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

ssm复习

​​​​​​其中环绕通知可以模拟出其他所有的通知只在调用方法前做事情-------前置通知用trycatch在finally里面写的东西就是------后置通知用trycach在try大括号结束之前原始方法调用之后的通知就是-------返回后通知catch模拟--------抛出异常后通知。

red_Apple_3_11的博客 1054

SSM重点复习

使用@RequestBody注解将json数据转换为Java对象前提:导入jackson依赖、使用注解@EnableWebMvc(配置json转换器)//接受Cookie//接受请求头 使用@RequestHeader共享域:request\session\servletcontext\model家族。

qq_74924951的博客 741

SSM+Spring Boot+Vue.js3期末复习

SSM+Spring Boot+Vue.js3期末复习

2301_80057732的博客 1263

尚硅谷复习SSM

我任然在往河里撒沙子。

qq_57953684的博客 246

SSM期末复习

MyBatis 是一款优秀的基于java的·持久层框架,它简化了 JDBC 操作,通过 XML 或注解将 SQL 语句与 Java 对象映射,实现数据持久化。内容84:实体类别名,环境管理,事务管理方式,数据源,mapper映射文件路径(可使用package但是有前提)切入点:一个正则表达式,execution(返回值类型,包名,包里具体对象,对象的方法,(方法的参数))execution(修饰符可省略,返回值类型,类名可省略,方法名*可代替所有方法(参数))如果是mybatis,用动态sql)

m0_74943996的博客 413

Java ee复习2 填空题

2.(填空题) Spring的功能模块被有组织地分散到约20个模块中,这些模块分布在( )(Core Container)层、( )/集成(Data Access/Integration)层、Web层、( )(Aspect Oriented Programming,AOP)模块、植入(Instrumentation)模块、( )(Messaging)和测试(Test)模块中。在OOP中,以( )作为程序的基本单元,而AOP中的基本单元是( )(切面)。在代理方法中,需要通过( )实现动态代理。

m0_74964090的博客 701

SSM框架之使用注解开发

SSM框架之使用注解开发 注解 小巧,方便,本意是便于开发。 但注解缺比较繁多,功能复杂,个数多,学多了以后就比较会容易忘记。这篇的目的就是复习一下SSM框架中之前用到的所有注解 MyBatis篇 首先就是用于Mapper接口中的4个CRUD注解和@Param注解 @Select 注解 同 @Insert @Update @Delete 在Mapper接口中,加在声明的方法上,并接上sql语句。 @Select("select * from user where id = #{id}") User ge

weixin_44405182的博客 1661

预备春招面试复习第一篇-----SSM框架

前言 为什么要先准备框架内容的复习呢? 个人是因为简历平平,只有俩项目还看得过去,新年的首发面试就凉在项目上,上来便是轰炸项目和框架.后来反省了下,框架知识也是一块很重要的内容.面试首发一般都是针对简历的项目开始考察. 后来看了一些别人的面经,很多都是上来就扯项目,你说要是连第一关框架都入不了面试官的眼,那还指望其他加分吗? 尤其当我知道别人二面全怼项目的时候,才意识到框架其实是面试的大头.那些只...

qq_38409944的博客 1014

ssm复习总结

复习记录

2301_80057732的博客 546

SSM·面试题

ssm初级面试题 ##1.1 答: ##1.1 何为Spring容器?Spring Bean容器与Spring IOC容器有什么不同吗? 答:用于创建bean对象,管理bean对象的那个容器;Spring IOC容器本质上指的就是Spring Bean容器,Spring Bean容器中最核心一个机制是IOC机制(控制反转),所以有时候又将spring bean容器称之为Spring IOC容器。 ##1.2 Spring IOC 如何理解? 答:答:IOC 是Spring中提供一种控制反转机制

weixin_47255020的博客 389
上一篇: SSM复习总结-Spring IOC
下一篇: SSM复习-Spring整合MyBatis
迷失的小鹿
博客等级 码龄8年 1万+粉丝 199原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值