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
来源:oschina
链接:https://my.oschina.net/u/140593/blog/204694