AOP实现的三种方式

AOP实现的三种方式

说说为什么要使用AOP编程:
AOP(面向切面编程)是OOP(面向对象编程)发展而来,在OOP编程中,每一个对象都有自己特定的功能,但是如果我们需要引入公共的功能时候,那么如果继续使用OOP编程思想的话,就会导致大量代码重用,而不利于模块的重用。而AOP编程则是将一些公共业务封装起来,为每一个需要使用这些公共业务的对象提供相应业务(通过代理实现)。一般将公共业务封装起来的类就是切面类,也就是我们切面编程所说的切面。

下面我们给对象添加一个公共业务:日志输出。
即在方法执行前后都在控制台输出一句话。
通过这个案例,简单介绍下AOP实现的三种方式。

先给出一个测试类代码:

接口类:

public interface UserService { 
    public void add();
    public void delete();
    public void update();
    public void select();

}

实现类:

public class UserServiceImpl implements UserService{ 

    public void add() { 
        System.out.println("增加了一个用户");
    }

    public void delete() { 
     System.out.println("删除了一个用户"); }

    public void update() { 
        System.out.println("更新了一个用户");
    }

    public void select() { 
        System.out.println("查询了一个用户");
    }
}

AOP实现的三种方式:
1、使用Spring API原生接口

方法执行后输出日志:

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice { 
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable { 
        System.out.println("Spring API接口实现AOP,add方法执行后");
    }
}

方法执行前输出日志:

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice { 
    public void before(Method method, Object[] objects, Object o) throws Throwable { 
        System.out.println("Spring API接口实现AOP,add方法执行前");
    }
}

xml配置文件:

    <bean id="userService" class="com.zm.service.UserServiceImpl"/>
    <bean id="log" class="com.zm.log.Log"/>
    <bean id="AfterLog" class="com.zm.log.AfterLog"/>

    <!--方式一:使用Spring API原生接口-->
    <!--配置aop,添加此配置之后,开启动态代理模式来自动获取代理类对象,且测试类获取对象要转换成接口类型,否则保错-->
        <aop:config>
            <!--切入点 execution(要执行的位置),第一个*代表所有返回类型,(..)代表方法中所有参数。这里将add方法设置为切入点,即当调用add方法,公共业务将被引入-->
            <aop:pointcut id="pointcut" expression="execution(* com.zm.service.UserServiceImpl.add(..))"/>
            <!--执行环绕增加! advice代表要增加的功能 pointcut代表要把功能加给谁 和动态代理对象会实现更多的功能原理一样-->
            <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
            <aop:advisor advice-ref="AfterLog" pointcut-ref="pointcut"/>
        </aop:config>

2、自定义切面类 ,即切面自定义

自定义切面类,且封装公共业务(这里是日志功能)

public class DiyPointCut { 
    public void before(){ 
        System.out.println("使用自定义类实现AOP,delete方法执行前");
    }

    public void after(){ 
        System.out.println("使用自定义类实现AOP,delete方法执行后");
    }
}

xml配置文件:

    <bean id="diy" class="com.zm.diy.DiyPointCut"/>

    <aop:config>
        <!--自定义切面,ref引用类-->
        <aop:aspect ref="diy">
            <!--切入点 ,这里的切入点设置为delete方法,即调用delete方法时引入公共业务-->
            <aop:pointcut id="point" expression="execution(* com.zm.service.UserServiceImpl.delete(..))"/>
            <!--通知-->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>

3、通过注解实现:


import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

//注解实现Aop
@Aspect //标注这个类是切面类
public class AnnotationPointCut { 
    @Before("execution(* com.zm.service.UserServiceImpl.update(..))")
    public void before(){ 
        System.out.println("使用注解实现AOP,update方法执行前");
    }

    @After("execution(* com.zm.service.UserServiceImpl.update(..))")
    public void after(){ 
        System.out.println("使用注解实现AOP,update方法执行后");
    }
}

xml配置:

    <bean id="annotationPointCut" class="com.zm.diy.AnnotationPointCut"/>
    <!--开启注解支持-->
    <aop:aspectj-autoproxy/>

来测试一下结果:

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest { 
    public static void main(String[] args) { 
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //动态代理类实现了userService接口
        //通过userServiceImpl对象反射,动态代理生成对应代理类对象,并转换成UserService接口类型。
        UserService userService =  (UserService) context.getBean("userService");
        userService.add();
        userService.delete();
        userService.update();
    }
}

《AOP实现的三种方式》

这里通过三种方式实现AOP编程,这三种方式分别选择了三个不同的方法作为切入点,因此三个方法被执行时,分别会引入三个不同公共业务(这里的公共业务是日志输出)

注意:
很多原理写在注释中了,如果有不清楚的可以多看一下注释,或者直接评论留言,欢迎一起讨论,欢迎纠错!!

    原文作者:万事无Bug
    原文地址: https://blog.csdn.net/weixin_45264992/article/details/115898452
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞