总结切面编程AOP的注解式开发和XML式开发
2017-08-30 15:59
148 查看
有段日子没有总结东西了,因为最近确实有点忙,一直在忙于hadoop集群的搭建,磕磕碰碰现在勉强算是能呼吸了,因为这都是在自己的PC上,资源确实有点紧张(搭建过程后期奉上),今天难得大家都有空(哈哈哈~~~),给各位总结一下Java开发猿人尽皆知的Spring框架它的核心组件——AOP(面向切面编程)。
老规矩,首先给各位说说它吧。AOP作为面向切面编程,是一种横向抽取的思想体现,不错,有了"横向切"这个概念呢,我们就应该会联想到之后的横切面、切入点,接着你有可能就会闭上眼睛想入非非,但是哥们你千万不要走歪,咱们现在讨论的是Java领域的切面编程,啊哈哈哈~好了,既然是面向切面编程,那么就避免不了"切",都知道,咱们的项目都会从web层到service层到dao层依次执行,既然是切,那么就会从某个层和某个层之间切开,接着就会做一些我们想做的事儿。反正大概的意思就是我所理解的切面编程,譬如切面编程的底层采用动态代理实现,在Spring框架中具体是如何执行的,我就不在这儿啰嗦了,因为这个点儿我也对源码不是理解的那么透彻,一直在学习的路上,等后期吃到点儿精华再回来给各位完善,下面我就会将我使用2中方式实现AOP切面编程的案例给各位共享一下。
小小一张图,请给位笑纳:
![](https://images2017.cnblogs.com/blog/855612/201708/855612-20170830160244296-207898853.png)
Spring框架的AOP切面编程分为俩种:注解式开发和XML配置式开发。
项目结构图:
![](https://images2017.cnblogs.com/blog/855612/201708/855612-20170830152554546-1670263607.png)
![](https://images2017.cnblogs.com/blog/855612/201708/855612-20170830153124312-1897060230.png)
1、开启AOP注解解析器:
2、实现注解切面编程,附:切入点表达式,AOP切入点表达式的书写格式: 方法返回值 完整包名.类名.方法名(参数)。 注:如果方法返回值和参数类型不限则可以使用*代替,如果以什么什么开头的方法也可以使用*代替,就如我们配置spring管理事务的传播行为雷同。涉及到的AOP的通知类型,在第二种XML配置方式中会详细介绍,哥们儿别停继续看着。
3、只要你访问调用了service层中检索操作的方法,就会触发切面上的方法,我这里是只要用户进行检索操作,就会实时记录该次检索操作的检索时长。
![](https://images2017.cnblogs.com/blog/855612/201708/855612-20170830154207624-349494318.png)
4、效果如图:
![](https://images2017.cnblogs.com/blog/855612/201708/855612-20170830155636108-73174430.png)
1、更新操作的切面类:
2、通过spring的配置实现切面编程:
3、同理,只要你访问调用了service层中删除操作时就会触发切面类上的方法,我这里是当用户进行删除操作,则会记录执行删除操作的用户的IP地址并打印在日志中。
![](https://images2017.cnblogs.com/blog/855612/201708/855612-20170830155119983-2004543271.png)
4、效果如图:
![](https://images2017.cnblogs.com/blog/855612/201708/855612-20170830155817999-599001719.png)
[好了,哥们儿到站了,醒醒吧,是不是没什么技术含量,把你都看醉了,哈哈哈~~~后期会给各位奉上hadoop相关的文章,因为一直在学习的路上,天气甚好在首都向各位问好!]
老规矩,首先给各位说说它吧。AOP作为面向切面编程,是一种横向抽取的思想体现,不错,有了"横向切"这个概念呢,我们就应该会联想到之后的横切面、切入点,接着你有可能就会闭上眼睛想入非非,但是哥们你千万不要走歪,咱们现在讨论的是Java领域的切面编程,啊哈哈哈~好了,既然是面向切面编程,那么就避免不了"切",都知道,咱们的项目都会从web层到service层到dao层依次执行,既然是切,那么就会从某个层和某个层之间切开,接着就会做一些我们想做的事儿。反正大概的意思就是我所理解的切面编程,譬如切面编程的底层采用动态代理实现,在Spring框架中具体是如何执行的,我就不在这儿啰嗦了,因为这个点儿我也对源码不是理解的那么透彻,一直在学习的路上,等后期吃到点儿精华再回来给各位完善,下面我就会将我使用2中方式实现AOP切面编程的案例给各位共享一下。
小小一张图,请给位笑纳:
![](https://images2017.cnblogs.com/blog/855612/201708/855612-20170830160244296-207898853.png)
Spring框架的AOP切面编程分为俩种:注解式开发和XML配置式开发。
项目结构图:
![](https://images2017.cnblogs.com/blog/855612/201708/855612-20170830152554546-1670263607.png)
AOP注解式开发:
首先我们使用注解式开发,最重要的一点就是能够让这些注解生效,何为生效?就是能够让它们活着看到spring框架的临幸,为什么说这个不起眼的问题呢,我在昨天使用注解都开发完了,但是怎么也执行不到切面上的方法,说白了就是注解没有扫描到,按理论说,切面都是会出现在service层前后,也就是说一般切面会作用在service层上,比如:在更新操作前进行权限校验、在检索操作时记录检索时长等等。那么我们通常使用spring的容器来扫描这些注解,但是在一些springMVC和spring共存的项目中,我们还不得不注意一下它们父子容器的关系,千万不要认为父子容器和谐共存,和谐共事【这里打个广告:有关父子容器的问题,请参考http://www.cnblogs.com/1315925303zxz/p/7211037.html】。我这里扫描切面是由spring容器完成的,因为我的切面类都在service层中了,所以我的切面组件的注解是由父容器spring的配置文件扫描的:![](https://images2017.cnblogs.com/blog/855612/201708/855612-20170830153124312-1897060230.png)
1、开启AOP注解解析器:
<!-- 【启动AOP的注解解析器】(基于注解方式必须添加该注解解析器) --> <aop:aspectj-autoproxy/>
2、实现注解切面编程,附:切入点表达式,AOP切入点表达式的书写格式: 方法返回值 完整包名.类名.方法名(参数)。 注:如果方法返回值和参数类型不限则可以使用*代替,如果以什么什么开头的方法也可以使用*代替,就如我们配置spring管理事务的传播行为雷同。涉及到的AOP的通知类型,在第二种XML配置方式中会详细介绍,哥们儿别停继续看着。
@Component @Aspect //声明这是一个切面类 public class SelecctAop { public static final String REGEX_IP_ADDR = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}"; private Date startDate = null; //专门用于存放开始时间 /** * 定义一个切入点 */ @Pointcut("execution(* cn.base.service.*.find*(..))") private void selectPointcut(){} /** * 检索开始前的时间记录 * @return * @throws Exception */ @Before("selectPointcut()") //通知类型 public void startTime() throws Exception{ String hostAddress = InetAddress.getLocalHost().getHostAddress(); //获取操作用户的IP地址 boolean isLegal = hostAddress.matches(REGEX_IP_ADDR); //验证IP地址 if(StringUtil.isNullOrBlank(hostAddress) && !isLegal){ //如果IP地址为空并且IP地址不合法 System.err.println("=============警告:非法用户操作=============="); } startDate = DateTimeUtils.getCurrentDate("yyyy-MM-dd HH:mm:ss"); //开始时间 System.err.println(startDate+"【开始】==="+hostAddress+"用户开始操作"); } /** * 检索结束后的时间记录、共计操作时长 * @throws Exception */ @After("selectPointcut()") //通知类型 public void timeConsuming() throws Exception{ String hostAddress = InetAddress.getLocalHost().getHostAddress(); //获取操作用户的IP地址 boolean isLegal = hostAddress.matches(REGEX_IP_ADDR); //验证IP地址 if(StringUtil.isNullOrBlank(hostAddress) && !isLegal){ //如果IP地址为空并且IP地址不合法 System.err.println("=============警告:非法用户操作=============="); } Date endDate = DateTimeUtils.getCurrentDate("yyyy-MM-dd HH:mm:ss"); //结束时间 System.err.println(endDate+"【终止】==="+hostAddress+"用户结束操作"); long startTime = startDate.getTime(); long endTime = endDate.getTime(); long time = endTime - startTime; System.err.println("================【共计耗时:" + time+ "】====================="); } public static void main(String[] args) { } }
3、只要你访问调用了service层中检索操作的方法,就会触发切面上的方法,我这里是只要用户进行检索操作,就会实时记录该次检索操作的检索时长。
![](https://images2017.cnblogs.com/blog/855612/201708/855612-20170830154207624-349494318.png)
4、效果如图:
![](https://images2017.cnblogs.com/blog/855612/201708/855612-20170830155636108-73174430.png)
XML配置式开发:
这种方式相对来说比较原始一点儿,就是通过在spring的核心配置文件中进行配置实现AOP切面编程,就是通过将切面类交由spring容器管理,然后通过spring容器的配置将切面类作用与相关业务方法上。1、更新操作的切面类:
package cn.base.service.aspect; import java.net.InetAddress; import java.net.UnknownHostException; import com.zxz.utils.DateTimeUtils; import com.zxz.utils.StringUtil; /** * 更新操作切面类:执行删除、修改、保存操作时需配置的切面类。[基于XML配置方式实现] * @author zxz */ public class UpdateAop { public static final String REGEX_IP_ADDR = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}"; /** * 用户进行更新操作之前的IP记录 */ public void recordIP(){ String hostAddress = ""; try { hostAddress = InetAddress.getLocalHost().getHostAddress(); //获取操作用户的IP地址 boolean isLegal = hostAddress.matches(REGEX_IP_ADDR); //验证IP地址 if(StringUtil.isNullOrBlank(hostAddress) && !isLegal){ //如果IP地址为空并且IP地址不合法 System.err.println("=============警告:非法用户操作=============="); } } catch (UnknownHostException e) { e.printStackTrace(); } System.err.println("【==="+DateTimeUtils.getCurrentMsLocal() + "---IP为:" + hostAddress + "进行了更新操作。===】"); } public static void main(String[] args) throws Exception { // String hostAddress = InetAddress.getLocalHost().getHostAddress(); // System.out.println(hostAddress); // System.out.println(hostAddress.matches(REGEX_IP_ADDR)); } }
2、通过spring的配置实现切面编程:
<!-- 配置更新切面类 --> <bean id="updateAop" class="cn.base.service.aspect.UpdateAop"/> <!-- spring的aop配置(基于XML方式的) --> <aop:config> <!-- 配置切入点: AOP切入点表达式的书写格式: 方法返回值 完整包名.类名.方法名(参数)。 注:如果方法返回值和参数类型不限则可以使用*代替。 --> <aop:pointcut expression="execution(* cn.base.service.*.delete*(..))" id="updatePointcut"/> <!-- 配置切面 --> <aop:aspect ref="updateAop"> <!-- 切面的通知类型: AOP的通知类型有: 1、前置通知【before】在方法执行之前进行增强,获得切入点信息。 2、后置通知【after】在方法执行之后进行增强,获得方法的返回值。 3、环绕通知【around】在方法执行前后进行增强,[阻止]目标方法执行。 4、异常抛出通知【after-throwing】在方法执行出现异常的时候进行增强,获得异常信息。 5、最终通知【after-returning】无论方法是否出现异常,最终通知中代码总是会执行的。 --> <aop:before method="recordIP" pointcut-ref="updatePointcut"/> </aop:aspect> </aop:config>
3、同理,只要你访问调用了service层中删除操作时就会触发切面类上的方法,我这里是当用户进行删除操作,则会记录执行删除操作的用户的IP地址并打印在日志中。
![](https://images2017.cnblogs.com/blog/855612/201708/855612-20170830155119983-2004543271.png)
4、效果如图:
![](https://images2017.cnblogs.com/blog/855612/201708/855612-20170830155817999-599001719.png)
[好了,哥们儿到站了,醒醒吧,是不是没什么技术含量,把你都看醉了,哈哈哈~~~后期会给各位奉上hadoop相关的文章,因为一直在学习的路上,天气甚好在首都向各位问好!]
相关文章推荐
- 总结切面编程AOP的注解式开发和XML式开发
- 对JAVA中MVC设计模式、JAVAWEB的三层架构、AOP面向切面编程的总结
- Spring容器切面编程 aop注解开发 五中通知类型
- 关于spring的aop(切面编程)配置总结
- Spring AOP编程(两种:1,传统的AOP切面编程 2,基于aspectj框架切点传统开发)
- Spring 3.x企业开发(三)之AOP面向切面编程
- 移动项目开发笔记(C#泛型编程基础知识总结)
- 面向切面编程AOP的浅显理解(一)
- Spring面向切面编程——Spring实现AOP方式——通过注解实现
- AOP面向切面编程
- Spring--AOP--面向切面编程
- 什么是面向切面编程AOP--知识点汇总
- python 多个装饰器组合应用,实现面向切面之AOP编程
- Spring AOP 面向切面编程相关注解
- spring-Aop切面编程
- Liferay7 BPM门户开发之36: 使用Portlet filters过滤器做切面AOP
- 深入分析JavaWeb 54 -- Spring中的AOP面向切面编程2
- 结合Java实例代码来理解 AOP--面向切面编程 中的各个术语
- Spring框架之浅析AOP切面编程