spring面向切面编程AOP详解

spring面向切面编程AOP详解

文章目录

  • spring面向切面编程AOP详解
  • 一、什么是 AOP?
    • 1.AOP 相关概念
    • 2.AOP 的作用及其优势
    • 3.AOP 的底层实现
  • 二、基于 XML 的 AOP 开发
    • 1.快速入门
  • 三、基于注解的 AOP 开发
  • 总结


一、什么是 AOP?

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

1.AOP 相关概念

Spring 的 AOP 实现底层就是对上面的动态代理的代码进行了封装,封装后我们只需要对需要关注的部分进行代码编写,并通过配置的方式完成指定目标的方法增强。

  1. Target(目标对象):代理的目标对象
  2. Proxy (代理):一个类被 AOP 织入增强后,就产生一个结果代理类
  3. Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
  4. Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义
  5. Advice(通知/ 增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知
  6. Aspect(切面):是切入点和通知(引介)的结合
  7. Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入

2.AOP 的作用及其优势

  • 作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强
  • 优势:减少重复代码,提高开发效率,并且便于维护

3.AOP 的底层实现

实际上,AOP 的底层是通过 Spring 提供的的动态代理技术实现的。在运行期间,Spring通过动态代理技术动态的生成代理对象,代理对象方法执行时进行增强功能的介入,在去调用目标对象的方法,从而完成功能的增强。


二、基于 XML 的 AOP 开发

1.快速入门

① 导入 AOP 相关坐标
② 创建目标接口和目标类(内部有切点)
③ 创建切面类(内部有增强方法)
④ 将目标类和切面类的对象创建权交给 spring
⑤ 在 applicationContext.xml 中配置织入关系
⑥ 测试代码

1.导入 AOP 相关坐标:


<dependency>
	<groupId>org.springframeworkgroupId>
	<artifactId>spring-contextartifactId>
	<version>5.0.5.RELEASEversion>
dependency>

<dependency>
	<groupId>org.aspectjgroupId>
	<artifactId>aspectjweaverartifactId>
	<version>1.8.13version>
dependency>

2.创建目标接口和目标类(内部有切点)

public interface TargetInterface {
    void save();
}
public class Target implements TargetInterface {

    public void save() {
        System.out.println("save running...");
    }
}

3.创建切面类(内部有增强方法)

// 切面,用来增强的方法(增强的部分)
public class MyAspect {

    public void before() {
        System.out.println("前置增强.....");
    }

    public void afterReturning() {
        System.out.println("后置增强.....");
    }

    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕前增强.....");
        Object proceed = pjp.proceed();
        System.out.println("环绕后增强.....");
        return proceed;
    }

    public void afterThrowing(){
        System.out.println("异常抛出增强..........");
    }

    public void after(){
        System.out.println("最终增强..........");
    }
}

4.将目标类和切面类的对象创建权交给 spring


<bean id="myAspect" class="com.ricky.aop.MyAspect"/>


<bean id="target" class="com.ricky.aop.Target"/>

5.在 applicationContext.xml 中配置织入关系


<aop:config>
   
   <aop:aspect ref="myAspect">
       
       
       
       
       
       
       <aop:around method="around" pointcut="execution(* com.ricky.aop.*.*(..))"/>
       
       <aop:after-throwing method="afterThrowing" pointcut="execution(* com.ricky.aop.*.*(..))"/>
       
       <aop:after method="after" pointcut="execution(* com.ricky.aop.*.*(..))"/>
   aop:aspect>
aop:config>

三、基于注解的 AOP 开发

提示:步骤一、二和三同上

4.将目标类和切面类的对象创建权交给 spring

@Component("target")
public class Target implements TargetInterface {
    @Override
    public void method() {
        System.out.println("Target running....");
    }
}

@Component("myAspect")
public class MyAspect {
    public void before() {
        System.out.println("前置代码增强.....");
    }
}

5.在切面类中使用注解配置织入关系

@Component("myAspect")
@Aspect
public class MyAspect {
	@Before("execution(* com.ricky.aop.*.*(..))")
	public void before(){
		System.out.println("前置代码增强.....");
	}
}

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


<context:component-scan base-package="com.ricky.aop"/>

<aop:aspectj-autoproxy>aop:aspectj-autoproxy>

总结

  • XML开发步骤:
  1. aop织入的配置
<aop:config>
	<aop:aspect ref=“切面类”>
		aop:before>
	aop:aspect>
aop:config>
  1. 通知的类型:前置通知、后置通知、环绕通知、异常抛出通知、最终通知
  2. 切点表达式的写法:execution([修饰符] 返回值类型 包名.类名.方法名(参数))
  • 注解aop开发步骤:
  1. 使用@Aspect标注切面类
  2. 使用@通知注解标注通知方法
  3. 在配置文件中配置aop自动代理

<aop:aspectj-autoproxy/>

注意:

1.切点表达式可以抽取:

@Pointcut("execution(* com.ricky.aop.User.add(..))")
public void pointDemo() {

}

@Before("pointDemo()")
public void before() {
    System.out.println("before...");
}

@After("execution(* com.ricky.aop.User.add(..))")
public void After() {
    System.out.println("After...");
}

2.如果有多个通知类对切入点增强,可以用@order注解来设置优先级(数字越小优先级越高)

@Component
@Aspect
@Order(1)
public class UserProxy2 {

    @Before("execution(* com.ricky.aop.User.add(..))")
    public void before() {
        System.out.println("before2....");
    }

}

你可能感兴趣的:(Spring,spring,代理模式,java)