栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring AOP 面向切面编程,XML和注解方式使用切面

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring AOP 面向切面编程,XML和注解方式使用切面

一、AOP
  • APO即Aspect Oriented Programing的缩写,字面直译的意思就是:面向切面编程。
  • AOP采用横向抽取机制,取代了传统的纵向继承体系中的重复性代码,是对OOP面向对象编程的一种补充和完善。AOP最重要或者说要达到的目的就是开发者在不修改不侵入源代码的前提下,给系统中的业务组件添加某种通用的功能。比如现在要统计系统中service层的所有方法的执行时间,如果使用面向对象的话只能在每个方法前后手动编写一段代码打印开始结束时间,来计算每个方法的执行时间;如果使用AOP就可以把计算时间的代码抽取出来,使用切面来在目标方法执行前后统计时间,不需要修改原来方法的源代码,方便了很多。
  • Spring AOP底层是通过JDK动态代理或者CGlib动态代理实现的。
类型原理什么情况下使用注意
JDK动态代理在运行时期,目标类加载后,为接口动态生成代理类,将切面织入到代理类中目标对象实现了接口,spring使用JDK的java.lang.reflect.Proxy类代理接口中的方法不能使用final修饰
CGlib动态代理动态生成目标类的子类,将切面织入到子类中目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类类或方法不能使用final修饰
二、AOP术语
  • Target:目标对象,被代理的对象;
  • Join Point:连接点,目标对象中要代理的方法;
  • PointCut:切入点,实际上被代理的方法;
  • Advice:通知,在切入点之前或者之后执行的方法,也是切面要完成的实际功能,(通知分为:前置通知、后置通知、异常通知、最终通知、环绕通知);
  • Aspect:切面,是对物体特征的抽象;
  • Introduction:引入,在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段;
  • Weaving:织入,将增强处理添加到目标对象中,并创建一个被增强的对象,这个过程就是织入。
三、XML方式使用AOP

1、创建UserService接口和UserServiceImpl实现类,UserServiceImpl就是我们要代理的类,即Target。

package com.aop;
// User接口
public interface UserService {

    String addUser(String name);
    String updateUser();
}
package com.aop;
// 实现类
public class UserServiceImpl implements UserService {

    @Override
    public String addUser(String name) {
        System.out.println("addUser...."+ name);
        return "添加user成功";
    }

    @Override
    public String updateUser() {
        System.out.println("updateUser....");
        return "修改user成功";
    }

}

2、创建MyAspect类,MyAspect就是我们的切面

package com.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

// 切面类
public class MyAspect {

    // Advice:前置通知
    public void myBefore(JoinPoint joinPoint){
        // 可以通过joinPoint获取代理对象和方法的相关信息
        
        System.out.println("目标方法执行前执行");
    }

    // Advice:后置通知
    public void myAfter(JoinPoint joinPoint){
        System.out.println("目标方法执行后执行");
    }

    // Advice:环绕通知
    public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("环绕之前:"+ joinPoint.getSignature().getName());
        // 必须自己手动执行目标方法
        Object obj = joinPoint.proceed();
        System.out.println("环绕之后:"+ joinPoint.getSignature().getName());
        return obj;
    }

    // Advice:异常抛出通知
    public void myThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("异常抛出:"+ joinPoint.getSignature().getName() + ", 异常信息" + e.getMessage());
    }
    // Advice:最终通知
    public void myFinal(JoinPoint joinPoint){
        System.out.println("最终:"+ joinPoint.getSignature().getName());
    }
}

3、在resources创建beans.xml配置文件




    
    
    
    
    
    
        
            
            
            
            
            

            

            
            
            

        
    


4、测试

package com.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

    public static void main(String[] args) {
        String xmlPath = "beans.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
        // 获得配置的目标类,实际上是拿到spring自动生成的代理类
        UserService userService3 = (UserService) applicationContext.getBean("userService");
        userService3.addUser("张三");
        userService3.updateUser();
    }
}

四、注解方式使用切面

@Before:前置通知
@AfterReturning:后置通知
@Around:环绕通知
@AfterThrowing 抛出
@After:最终通知
@PointCunt:统一管理表达式
@Aspect:表示自己是切面类

package com.aop_annotation;

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

// 切面类
@Aspect
@Component
public class MyAspect {

    @Pointcut(value = "execution(* com.aop..*.*(..))")
    private void myExce(){}

    // Advice:前置通知
    @Before("myExce()")
    public void myBefore(JoinPoint joinPoint){
        // 可以通过joinPoint获取代理对象和方法的相关信息
        
        System.out.println("目标方法执行前执行");
    }

    // Advice:后置通知
    @AfterReturning("myExce()")
    public void myAfter(JoinPoint joinPoint){
        System.out.println("目标方法执行后执行");
    }

    // Advice:环绕通知
    @Around("myExce()")
    public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("环绕之前:"+ joinPoint.getSignature().getName());
        // 必须自己手动执行目标方法
        Object obj = joinPoint.proceed();
        System.out.println("环绕之后:"+ joinPoint.getSignature().getName());
        return obj;
    }

    // Advice:异常抛出通知
    @AfterThrowing(value = "myExce()", throwing = "e")
    public void myThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("异常抛出:"+ joinPoint.getSignature().getName() + ", 异常信息" + e.getMessage());
    }
    // Advice:最终通知
    @After("myExce()")
    public void myFinal(JoinPoint joinPoint){
        System.out.println("最终:"+ joinPoint.getSignature().getName());
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/530827.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号