Spring笔记(2)

一、AOP简介

1.概念:

  • 面向切面编程(Aspect-Oriented Programming),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。

  • AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,提高代码的灵活性和可扩展性,AOP可以说也是这种目标的一种实现。

2.作用

在程序运行期间,在不修改源码的情况下对方法进行功能的增强

  • 日志记录,性能统计,安全控制,事务处理,异常处理等等wn及扩展

3.底层实现

AOP的动态代理技术

JDK代理

基于接口的动态代理技术

image-20210318161029482

cglib代理

基于父类动态代理技术

image-20210318161056876

4.知识要点

aop:面向切面编程

aop底层实现:基于jdk的动态代理和基于cglib的动态代理

aop的重点概念:

  • ​ Pointcut(切入点):被增强的方法
  • ​ Adivce(通知/增强):封装增强业务逻辑的方法
  • ​ Aspect(切面):切点+通知
  • ​ Weaving(织入):将切点与通知结合的过程

二、基于XML的AOP开发

1.快速入门

步骤

  1. 添加坐标,spring-context 和 aop

    <!--    spring-context-->
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>5.0.5.RELEASE</version>
        </dependency>
    <!--    aop-->
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.8.13</version>
        </dependency>
      </dependencies>
    
  2. 创建目标接口并实现目标接口(连接点,切入点)

    //接口类
    public interface TargetInterface {
        public void save();
    }
    
    //实现类
     @Override
        public void save() {
            System.out.println("saving..");
        }
    
  3. 创建切面类(内写增强方法)

    //切面类
    public class MyAspect {
        public void before(){
            System.out.println("前置增强。。。");
        }
    }
    
  4. 创建applicationContext.xml文件,并将目标对象切面类注入

    <!--    目标对象-->
        <bean id="target" class="AopLearn.Target"></bean>
    
    
    <!--    切面对象-->
        <bean id="myAspect" class="AopLearn.MyAspect"></bean>
    
  5. 引入aop命名空间

    xmlns:aop="http://www.springframework.org/schema/aop"
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
    
  6. 配置织入,告诉spring框架,哪些方法(切点)需要进行那些增强(前置、后置)

        <aop:config>
    <!--        声明切面-->
            <aop:aspect ref="myAspect">
    <!--            声明切点和通知-->
                <aop:before method="before" pointcut="execution(public void AopLearn.Target.save())">
            </aop:aspect>
        </aop:config>
    

2.切点表达式

表达式语法:

​ execution([修饰符] 返回值类型 包名.类名.方法名(参数))

注:

  • 返回值类型、包名、类名、方法名可以使用星号*代表任意
  • 访问修饰符可以省略
  • 包名与类名之间一个点.代表当前包下的类,两个点表示当前包及其子包下的类
  • 参数列表可以使用两个点…示任意个数,任意类型的参数列表

常用:

excution( com itheima.app. .* (..));**

​ 任意返回值 it黑马aop包下的 任意类的 任意方法

抽取(易于维护 ):

<!--            抽取切点表达式-->
            <aop:pointcut id="myPointcut" expression="execution(* AopLearn.*.*(..))"/>
<!--            使用抽取的切点表达式-->
            <aop:before method="before" pointcut-ref="myPointcut"/>

3.通知的类型

  • 前置通知:调用目标组件前,调用方面组件(before)

  • <aop:before method="before" pointcut="execution(public void AopLearn.Target.save())"></aop:before>
    
  • 后置通知:调用目标组件后,调用方面组件(after-returning)

  • 最终通知:调用目标组件后,在finally里调用方面组件(after)

  • 异常通知:目标组件发生异常时,调用方面组件。(after-throwing)

  • 环绕通知:调用目标组件前、后,分别调用一次方面组件。(around)

三、基于注解的AOP开发

1.快速入门

  1. 创建目标接口目标类

  2. 创建切面类

  3. 将目标类和切面类的创建权交给Spring管理,并设置切面类标识。 (生成bean

    
    //实现bean的注入
    @Component("target")
    public class Target implements TargetInterface {
        @Override
        public void save() {
            System.out.println("saving..");
        }
    }
    
    //实现bean的注入
    @Component("myAspect")
    //配置为切面类
    @Aspect
    public class MyAspect {
        //注解配置织入关系
        @Before("execution(* Annotation.*.*(..))")
        public void before(){
            System.out.println("anno前置增强。。。");
        }
    }
    
  4. 在切面类中使用注解配置织入关系

    public class MyAspect {
        //注解配置织入关系
        @Before("execution(* Annotation.*.*(..))")
        public void before(){
            System.out.println("anno前置增强。。。");
        }
    }
    
  5. 创建context命名空间

  6. 在配置文件中开启组件扫描AOP的自动代理

    <!--        开启组件扫描-->
            <context:component-scan base-package="Annotation"/>
    <!--    aop自动代理-->
            <aop:aspectj-autoproxy/>
    
  7. 测试

    @Test
    public void test02(){
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext-anno.xml");
        TargetInterface target = app.getBean(TargetInterface.class);
        target.save();
    }
    

2.切点表达式

抽取

/**
 * 定义切点表达式
 */
@Pointcut("execution(* Annotation.*.*(..))")
public void pointcut(){}

配置织入关系

@Before("pointcut()")
public void before(){
    System.out.println("anno前置增强。。。");
}

3.通知的类型

  • @Before --- 前置通知

  • @AfterReturning --- 后置通知

  • @Around --- 环绕通知(目标对象默认不执行,需要手动执行)

  • @After --- 最终通知

  • @AfterThrowing --- 异常抛出通知

4.注意

使用@Aspect标注切面类

一定配置aop自动代理

<!--    aop自动代理-->
        <aop:aspectj-autoproxy/>
posted @ 2021-08-26 17:33  橡皮筋儿  阅读(42)  评论(0编辑  收藏  举报