动态AOP使用示例

前言

我们知道,使用面向对象编程(OOP)有一些弊端,当需要为多个不具有继承关系的对象引入一个公共的行为时,例如日志、安全检查等,我们只有在每个对象里引用公共的行为,这样程序中就产生了大量的重复代码,程序就不便于维护了,所以就有了一个面向对象编程的补充,即面向切面编程(AOP),AOP所关注的方向是横向的,不同于OOP的纵向。

  Spring中提供了AOP的实现,在低版本的Spring中定义一个切面比较的麻烦,需要实现特定的接口,并进行一些较为复杂的配置。在Spring2.0中AOP已经焕然一新,使用@AspectJ注解来定义一个切面就可以了。

动态AOP使用示例

(1)创建用于拦截的bean

  在实际的工作中,此bean可能是满足业务需要的核心逻辑,例如一个方法中可能封装着某个核心业务,但是,如果我们想要在这个方法前后加入日志来跟踪调试,如果直接修改源码并不符合面向对象的设计方法,而且随意改动原有代码也会造成一定的风险,还好Spring中帮我们做到了这一点。

public class Hello {

    private String tetStr = "testStr";

    public String getTetStr() {
        return tetStr;
    }

    public void setTetStr(String tetStr) {
        this.tetStr = tetStr;
    }

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

(2)创建Advisor

Spring中摒弃了最原始的繁杂配置方式而采用@AspectJ注解对POJO进行标注,使得AOP的工作大大简化,例如,在AspectJTest类中,我们要做的就是在所有的类的test方法执行前后分别在控制台中打印出beforeTest和afterTest,同时又使用环绕的方式在所有类的执行前后分别打印出before和after。在此需要注意如果要使用@AspectJ注解需要引入jar包:aspectjweaver-1.8.7.jar

@Aspect
public class AspectJTest {


    @Pointcut("execution(* *.test(..))")
    public void test(){

    }

    @Before("test()")
    public void beforeTest(){
        System.out.println("beforeTest");
    }

    @After("test()")
    public void afterTest(){
        System.out.println("afterTest");
    }

    @Around("test()")
    public Object aroundTest(ProceedingJoinPoint point){
        System.out.println("before");
        Object object = null;
        try {
            object = point.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

        System.out.println("after");
        return object;
    }
}

(3)创建配置文件

XML是Spring的基础。尽管Spring一再简化配置,并且大有使用注解取代XML配置之势,但是无论如何,至少现在XML还是Spring的基础。要在Spring中开启AOP功能,还需要在配置文件中做如下的声明:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--AOP声明 -->
    <aop:aspectj-autoproxy/>
    
    <bean id="hello" class="com.joe.aop.Hello"/>
    <bean class="com.joe.aop.AspectJTest"/>
</beans>

(4)测试。

public static void main(String[] args){
        //创建Spring上下文(加载bean.xml)
        ApplicationContext acx= new ClassPathXmlApplicationContext("spring-config.xml");
        Hello hello = (Hello) acx.getBean("hello");
        hello.test();
    }

运行结果:

before
beforeTest
test
after
afterTest

Spring实现了对所有类的test方法进行增强,使得辅助功能可以独立于核心业务之外,方便与程序的扩展和解耦。

参考:《Spring源码深度解析》 郝佳 编著:

作者:Joe
努力了的才叫梦想,不努力的就是空想,努力并且坚持下去,毕竟这是我相信的力量
原文地址:https://www.cnblogs.com/Joe-Go/p/10229214.html