AOP的实现原理

目录

1、AOP的介绍及其作用      

2、AOP常用框架  

3、常见术语

4、使用AOP的方式 

 4.1  自定义面向切面

4.2  注解的方式实现 

1、AOP的介绍及其作用      

AOP:就是面向切面编程,和OOP(面向对象编程)类似,也是一种编程思想

作用:横向抽取机制

  • 采用横向抽取机制(动态代理),取代了传统纵向继承机制的重复性代码,其应用主要体现

在事务处理、日志管理、权限控制、异常处理等方面

  • 分离功能性需求和非功能性需求,使开发人员可以集中处理某一个关注点或者横切逻辑,减少

对业务代码的侵入,增强代码的可读性和可维护性

  • 保证开发者在不修改源代码的前提下,为系统中的业务组件添加某种通用功能,AOP就是代理

模式的典型应用

2、AOP常用框架  

  • Spring AOP

使用的是动态代理,所谓的动态代理就是AOP框架不会修改字节码,而是每次运行的时候

你在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且

在特定的切点做了增强处理,并回调原对象的方法

  • AspectJ

静态代理,又称为编译时增强,AOP框架会在编译阶段生成AOP代理类,并将AspectJ切面

织入到Java字节码中,运行的时候就是增强之后的AOP对象

3、常见术语

  • Joinpoint(连接点):程序执行期间的某一个点,例如执行方法或处理异常时候的点。在 Spring AOP 中,连接点总是表示方法的执行。
  • Advice(通知):通知是指一个切面在特定的连接点要做的事情。通知分为方法执行前通知,方法执行后通知,环绕通知等。许多 AOP 框架(包括 Spring)都将通知建模为拦截器,在连接点周围维护一系列拦截器(形成拦截器链),对连接点的方法进行增强。
  • Pointcut(切点):一个匹配连接点(Join point)的谓词表达式。通知(Advice)与切点表达式关联,并在切点匹配的任何连接点(Join point)(例如,执行具有特定名称的方法)上运行。切点是匹配连接点(Join point)的表达式的概念,是AOP的核心,并且 Spring 默认使用 AspectJ 作为切入点表达式语言。
  • Aspect(切面):它是一个跨越多个类的模块化的关注点,它是通知(Advice)和切点(Pointcut)合起来的抽象,它定义了一个切点(Pointcut)用来匹配连接点(Join point),也就是需要对需要拦截的那些方法进行定义;它定义了一系列的通知(Advice)用来对拦截到的方法进行增强;
  • Target object(目标对象):被一个或者多个切面(Aspect)通知的对象,也就是需要被 AOP 进行拦截对方法进行增强(使用通知)的对象,也称为被通知的对象。由于在 AOP 里面使用运行时代理,所以目标对象一直是被代理的对象。
  • AOP proxyAOP 代理):为了实现切面(Aspect)功能使用 AOP 框架创建一个对象,在 Spring 框架里面一个 AOP 代理要么指 JDK 动态代理,要么指 CgLIB 代理。
  • Weaving(织入):是将切面应用到目标对象的过程,这个过程可以是在编译时(例如使用 AspectJ 编译器),类加载时,运行时完成。Spring AOP 和其它纯 Java AOP 框架一样,是在运行时执行植入。
  • Advisor这个概念是从 Spring 1.2的 AOP 支持中提出的,一个 Advisor 相当于一个小型的切面,不同的是它只有一个通知(Advice),Advisor 在事务管理里面会经常遇到

 Advice增强处理类型

  •  方法名处理增强
  • before(前置通知):通知方法在目标方法调用之前执行
  • after(后置通知):通知方法在目标方法返回或异常后调用,无论如何都会执行
  • after-returning(返回后通知):通知方法会在目标方法返回后调用,如果抛出异常则不执行
  • after-throwing(抛出异常通知):通知方法会在目标方法抛出异常后调用
  • around(环绕通知):通知方法会将目标方法封装起来

注解的方式处理增强

  •  @Aspect                     用于定义一个切面。                                          
  •  @Pointcut                  用于定义一个切入点。                                        
  •  @Before                     用于定义前置通知,相当于 BeforeAdvice。                     
  •  @AfterReturning        用于定义后置通知,相当于 AfterReturningAdvice。             
  •  @Around                    用于定义环绕通知,相当于MethodInterceptor。                 
  •  @AfterThrowing         用于定义抛出通知,相当于ThrowAdvice。                       
  •  @After                        用于定义最终final通知,不管是否异常,该通知都会执行。

4、使用AOP的方式 

 4.1  自定义面向切面

a.要配置pom.xml文件


<!--aop依赖1:aspectjrt -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.5</version>
</dependency>
 
<!--aop依赖2:
aspectjweaver -->

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver </artifactId>
    <version>1.9.5</version>
</dependency>

b.创建代理类

public  class  UserAOP{

//前置增强
public  void  beforeAdvice(JoinPoint  p){
    System.out.println("前置增强"+p.getSignature().getName()+"方法");
}


//后置增强(最终增强)
public  void  afterAdvice(JoinPoint  p){
    //p.getSignature().getName()被增强的方法名
    System.out.println("后置增强"+p.getSignature().getName()+"方法");
}

//后置返回增强
public  Object  afterReturnAdvice(Object  obj)throwsThrowable{
    System.out.println("后置返回增强"+obj);
    return  obj;
}

//环绕增强
public  Object  aroundAdvice(ProceedingJoinPoint  p){
    //p.getTarget()获取被增强方法的位置
    //p.getArgs()获取被增强方法的参数
    System.out.println("基于环绕增强"
        +p.getTarget()
        +"的"+p.getSignature().getName()
        +"方法,参数:"
        +Arrays.toString(p.getArgs()));
    Object  rs=null;
    try{
        rs=p.proceed();//调用目标方法返回目标方法的返回结果
    }catch(Throwable  e){

        System.out.println("基于环绕增强:"
            +p.getTarget()
            +"的"
            +p.getSignature().getName()
            +"方法,参数:"

    +Arrays.toString(p.getArgs())+"发生异常:"+e.getMessage());

    }finally{
        System.out.println("基于环绕增强的后置处理");
    }
    return  rs;
}

//异常增强
public  void  afterThrowAdvice(JoinPoint  p,RuntimeException  e){
    System.out.println("异常增强"
    +p.getSignature().getName()+"发生了"
    +e.getMessage()+"异常");
    }

}

 c.手动配置切面

<bean  id="userAOP"  class="com.lyt.demo03.UserAOP"></bean>
<bean  id="userService"  class="com.lyt.demo02.UserServiceImpl"></bean>
<!--面向切面-->
<aop:config>
    <aop:pointcut  id="pointcut" expression="execution(* com.lyt.demo02.*.*(..))"/>
        <aop:aspect  ref="userAOP">
            <!--前置增强-->
            <aop:before  method="beforeAdvice" pointcut-ref="pointcut"/>
            <!--后置增强返回值returning="obj"-->
            <aop:after-returning returning="obj" method="afterReturnAdvice" pointcut-ref="pointcut"/>
            <!--环绕增强-->
            <aop:around  method="aroundAdvice" pointcut-ref="pointcut"/>
            <!--异常增强异常throwing="e"-->
            <aop:after-throwing throwing="e" method="afterThrowAdvice" pointcut-ref="pointcut"/>
            <!--最终增强-->
            <aop:after  method="afterAdvice"  pointcut-ref="pointcut"/>
            </aop:aspect>
</aop:config>

4.2  注解的方式实现 

 第一步:开启扫描
<context:component-scan  base-package="com.lyt"/>
第二步:开启注解切面
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

代理类
@Aspect           //面向切面
@Component    //将UserAOP注解为Bean
public  class  UserAOP{
	@Pointcut("execution(*com.lyt.demo02.*.*(..))")
	public  void  pointcut(){}
	//前置增强
	@Before("pointcut()")
	public  void  beforeAdvice(JoinPoint  p){
		System.out.println("前置增强"+p.getSignature().getName()+"方法");
	}
	
	//后置增强(最终增强)
	@After("pointcut()")
	public  void  afterAdvice(JoinPoint  p){
		//p.getSignature().getName()被增强的方法名
		System.out.println("后置增强"+p.getSignature().getName()+"方法");
	}
	//后置返回增强
	@AfterReturning(value="pointcut()",returning="obj")
	public  Object  afterReturnAdvice(Object  obj)throwsThrowable{
		System.out.println("后置返回增强"+obj);
		return  obj;
	}
	//环绕增强
	@Around("pointcut()")
	public  Object  aroundAdvice(ProceedingJoinPoint  p){
		//p.getTarget()获取被增强方法的位置
		//p.getArgs()获取被增强方法的参数
		System.out.println("基于环绕增强"+p.getTarget()+"的"+p.getSignature().getName()+"方法,参数:"
		+Arrays.toString(p.getArgs()));
		Object  rs=null;
		try{
			rs=p.proceed();//调用目标方法返回目标方法的返回结果
		}catch(Throwable  e){
			System.out.println("基于环绕增强:"+p.getTarget()+"的"+p.getSignature().getName()+"方法,参数:"
			+Arrays.toString(p.getArgs())+"发生异常:"+e.getMessage());
		}finally{
			System.out.println("基于环绕增强的后置处理");
		}
		return  rs;
	}
	//异常增强
	@AfterThrowing(value="pointcut()",throwing="e")
	public  void  afterThrowAdvice(JoinPoint  p,RuntimeException  e){
		System.out.println("异常增强"
		+p.getSignature().getName()+"发生了"
		+e.getMessage()+"异常");
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值