• spring学习总结013 --- AOP面向切面编程


    AOP能够在应用程序指定位置、指定时机,植入指定功能,并且不影响原程序的功能;

    最简单的而举例:在已有应用程序的所有方法调用前后分别添加日志;我们肯定不能修改程序,在每个方法前后添加日志,这样做工作量大,容易遗漏,更重要的是违背了“开闭原则”

    AOP面向切面编程不是spring框架独有的,其他比较著名的框架是AspectJ;我们常说的spring AOP是spring整合和AspectJ,当然spring自身也实现了AOP,不过比较厚重(在spring事务中有应用)

    一些基本概念

    • 通知(Advice): AOP 框架中的增强处理。通知描述了切面何时执行以及如何执行增强处理。
    • 连接点(join point): 连接点表示应用执行过程中能够插入切面的一个点,这个点可以是方法的调用、异常的抛出。在 Spring AOP 中,连接点总是方法的调用。
    • 切点(PointCut): 可以插入增强处理的连接点。
    • 切面(Aspect): 切面是通知和切点的结合。
    • 引入(Introduction):引入允许我们向现有的类添加新的方法或者属性。
    • 织入(Weaving): 将增强处理添加到目标对象中,并创建一个被增强的对象,这个过程就是织

    这些概念比较抽象,需要在实际应用中理解

    spring AOP实例(注解方式)

    1、添加maven依赖:spring-aop、spring-aspects、spring-context

    2、创建spring配置类

    @Configuration // 声明为spring配置类
    @ComponentScan(basePackages = {"com.demo"}) // 扫描com.demo包下的bean定义
    @EnableAspectJAutoProxy // 为切面类创建代理, 植入增强
    public class AopConfig {
    }

    3、定义切面

    @Slf4j
    @Aspect // 声明为切面
    @Component
    public class LogAspect {
    
        // 定义切点及切点表达式, 即声明在哪些方法织入切面
        @Pointcut("execution(public void com.demo.service.*.*(*))")
        public void pointcut() {
        }
    
        @Before("pointcut()") // 织入前置通知
        public void before(JoinPoint joinPoint) {
            log.info("Before invoke method:{}", joinPoint.getSignature().getName());
        }
    }

    4、业务代码,spring会使用CGLIB为该类生成代理类

    @Service
    public class AopService {
    
        public void func1(String name) {
            log.info("================Invoke func1, name:{}================", name);
        }
    }

    5、测试代码

        @Test
        public void test_cglib_proxy() {
            AopService aopService = applicationContext.getBean(AopService.class);
            aopService.func1("bale");
            log.info("AopService class:{}", aopService.getClass().getName());
        }

    执行结果:

    前面的业务代码采用CGLIB创建代理类,如果想采用JDK方式创建代理类,那么需要业务方法为接口实现类,举例如下:

    接口:

    public interface AopServiceIntf {
        public void printSomething(String name);
    }

    实现类:

    @Slf4j
    @Component
    public class AopServiceIntfImpl implements AopServiceIntf {
    
        @Override
        public void printSomething(String name) {
            log.info("=====================Invoke printSomething, name:{}====================", name);
        }
    }

    测试类:

        @Test
        public void test_jdk_proxy() {
            AopServiceIntf aopServiceIntf1 = (AopServiceIntf) applicationContext.getBean("aopServiceIntfImpl");
            aopServiceIntf1.printSomething("bale1");
            log.info("AopServiceIntf1 class:{}", aopServiceIntf1.getClass().getName());
        }

    执行结果:

    spring AOP实例(XML配置方式)

    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: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.demo" />
    
        <aop:aspectj-autoproxy />
    
        <bean class="com.demo.aop.LogXmlAspect" id="logXmlAspect" />
    
        <aop:config>
            <aop:aspect id="logAspect" ref="logXmlAspect">
                <aop:pointcut id="logPointcut" expression="execution(public void com.demo.service.*.*(*))"/>
                <aop:before method="before" pointcut-ref="logPointcut" />
            </aop:aspect>
        </aop:config>
    </beans>

    2、切面类

    @Slf4j
    public class LogXmlAspect {
    
        public void before(JoinPoint joinPoint) {
            log.info("Before invoke method:{}", joinPoint.getSignature().getName());
        }
    }

    3、同样的测试类和业务类,执行结果:

    指定代理方式

    <aop:aspectj-autoproxy proxy-target-class="true" />

    proxy-target-class="true"表示使用CGLIB代理方式

    proxy-target-class="false"为默认值,如果委托类为接口实现类则使用JDK代理方式,否则采用CGLIB代理方式

  • 相关阅读:
    javaweb学习总结(二十三)——jsp自定义标签开发入门
    javaweb学习总结(二十二)——基于Servlet+JSP+JavaBean开发模式的用户登录注册
    MyEclipse使用总结——设置MyEclipse使用的Tomcat服务器
    XML学习总结(二)——XML入门
    XML学习总结(一)——XML介绍
    使用java中replaceAll方法替换字符串中的反斜杠
    MyEclipse使用总结——设置MyEclipse开发项目时使用的JDK
    MyEclipse使用总结——修改MyEclipse默认的Servlet和jsp代码模板
    使用js加载器动态加载外部Javascript文件
    JavaScript获取浏览器类型与版本
  • 原文地址:https://www.cnblogs.com/sniffs/p/13307000.html
Copyright © 2020-2023  润新知