Spring AOP的一个使用例子

爱⌒轻易说出口 提交于 2020-03-09 21:50:03

0.前言

    学习Spring,肯定会了解IOC和AOP的思想,除了Spring的基本使用,自己在实际应用中,还真没特意使用过AOP的功能。最近有一个项目使用到了Spring,由于之前也没有Spring的实际工作经验,加上项目比较着急,所以有很多细节不完善的地方。下面介绍AOP使用的一个例子,有不对或者更好的解决方法,欢迎指正。

1.功能需求

    项目是一个学习小组,用户可以创建小组,加入小组,离开小组,以及其它一系列功能。在小组首页里有一个小组动态。这就需要我们在程序中,处理用户基本操作以外,还要保存相应的小组动态。

2.基本实现

    首先想到的就是写一个公共的方法,在需要的地方进行调用。因为里面有两个DAO操作,所以封装成了一个service方法。在不同的service中注入service调用这个方法。这个方法大概需要几个参数,记录小组id,用户id,以及动态的type

public void addTeamNewsLog(long team_id,long user_id,int type){
        long ref = studyTeamInfoDAO.getSeqAllRef();
        StudyTeamNews news =new StudyTeamNews();
        news.setRef(new BigDecimal(ref));
        news.setTeamId(new BigDecimal(team_id));
        news.setUserId(new BigDecimal(user_id));
        news.setType((short) type);
        studyTeamNewsDAO.insertSelective(news);
    }

比如

1.创建小组 (首先创建小组, 然后小组创建动态 , 最后添加关联)

2.记录用户和小组关联(先添加关联,再记录用户加入动态,删除用户申请消息)


    类似这样的情况,程序中大概还有几个地方。

3.功能改进

    今天项目上线了,功能一切正常,下午在看代码的时候,突然想到Spring有AOP的功能,我可以考虑一下AOP去实现这个功能。

    @黄勇 博客的 《AOP那些事儿》http://my.oschina.net/huangyong/blog/161402

    找到了Spring AOP的功能实现  12. Spring + AspectJ(基于注解:通过 AspectJ execution 表达式拦截方法)

    在Spring的配置文件中加入

<aop:aspectj-autoproxy proxy-target-class="true"/>

   在项目下新建一个package,创建了一个Aspect类,加入一个新方法

    1.首先通过AspectJ execution表达式 写拦截的方法 (Intellij IDEA有智能提示)

    2.在after()方法打一个断点 

@Around("execution(* com.etiantian.studyteam.dao.StudyTeamInfoDAO.insert(..))")
    public Object addTeamOk(ProceedingJoinPoint pjp)throws  Throwable{
        Object result = pjp.proceed();
        after();
        return result;
    }

    重启服务器....创建战队....OK,进入断点了,说明我们的AOP功能起作用了,下面我就可以记录动态了

    3.在pjp.proceed();方法打一个断点,然后debug进去 看看pjp中有什么东西,发现有方法名,有参数,再上网查一下ProceedingJoinPoint这个类,可以通过getArgs 获得切入方法的参数。

    4.根据自己的功能需要,修改方法

@Around("execution(* com.etiantian.studyteam.service.facede.StudyTeamJUserService.saveStudyTeamJUser(..))")
    public Object addTeamUser(ProceedingJoinPoint pjp)throws Throwable {
        long team_id=Long.parseLong(pjp.getArgs()[0].toString());
        long user_id=Long.parseLong(pjp.getArgs()[1].toString());
        Object result = pjp.proceed();
        addStudyTeamLog(team_id, user_id, StudyTeamBaseAction.ADD_TEAM_USER);
        return result;
    }

    @Around("execution(* com.etiantian.studyteam.dao.StudyTeamInfoDAO.insert(..))")
    public Object addTeamOk(ProceedingJoinPoint pjp)throws  Throwable{
        Object result = pjp.proceed();
        StudyTeamInfo st =(StudyTeamInfo)pjp.getArgs()[0];
        addStudyTeamLog(st.getTeamId().longValue(), st.getcUserId().longValue(), StudyTeamBaseAction.ADD_TEAM_OK);
        return result;
    }

    private void addStudyTeamLog(long team_id,long user_id,int type){
        studyTeamInfoService.addTeamNewsLog(team_id,user_id,type);
    }

   5.注释掉原有service中的所有 addTeamNewsLog方法调用,测试一切正常... 

4.总结

    自己在项目中,也是先实现基本功能的增删改查,然后再不断完善功能,比如小组动态就是后来加入的,当然需要修改原来的程序。

    如果我们使用AOP的方法,那么原有程序我们就可以不用修改了,只用找到切入点,根据需要在切入点的前后加上相应的操作。而且维护起来也比较容易,比如我们想去掉某个类型的日志记录,或者加入新的动态记录,都不用再去修改源代码。

   当然可以参考@黄勇 博客的 《AOP那些事儿》http://my.oschina.net/huangyong/blog/161402,采用第十三种,通过自定义注解的方式进行实现,这样就不用写多个方法了....

  注:使用Spring+Aspectj 的AOP可能需要Cglib 的jar   


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!