zoukankan      html  css  js  c++  java
  • 动态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
    努力了的才叫梦想,不努力的就是空想,努力并且坚持下去,毕竟这是我相信的力量
  • 相关阅读:
    目录路径加反斜杠和不加的区别
    window端口号被占用解决
    个人博客设计记录
    2017/12/15
    添加code到github上
    跨域简介
    客户端存储
    window.name跨域
    BZOJ1305: [CQOI2009]dance跳舞
    BZOJ4872: [Shoi2017]分手是祝愿
  • 原文地址:https://www.cnblogs.com/Joe-Go/p/10229214.html
Copyright © 2011-2022 走看看