AspectJ实现AOP

上一篇文章Spring框架(4)---AOP讲解铺垫,讲了一些基础AOP理解性的东西,那么这篇文章真正开始讲解AOP

通过AspectJ实现AOP要比普通的实现Aop要方便的多,所以第五篇文章有关SpringAOP我暂且不写,后面整理好了再补充上;

那我们首先还是讲一些有的没的的东西:

什么是Spring的AspectJ的AOP

      AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
  Spring2.0以后新增了对AspectJ切点表达式支持,@AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面
  新版本Spring框架,建议使用AspectJ方式来开发AOP

那我们先来一个小案例,还是以前面狗的案例举例:

1.导入相关架包

在原来的基础上导入下面四个架包:

  • spring-aop-4.2.0.RELEASE.jar
  • com.springsource.org.aopalliance-1.0.0.jar
  • spring-aspects-4.2.0.RELEASE.jar
  • com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

2.编写配置文件applicationContext.xml    导入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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here --> <!-- 配置注解bean所在的包 -->
<context:annotation-config/>
<context:component-scan base-package="com.study.spring.d_advisor"></context:component-scan>
<!-- 打开自动代理 -->
<aop:aspectj-autoproxy/>
</beans>

3.编写代理对象

 public class Dog {

     public void run() {
System.out.println("狗会跑");
} public void jump() { System.out.println("狗会跳"); } public void eat() { System.out.println("狗能吃");
}
}

4)编写切面类

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
//@Aspect声明当前类是一个切面
@Aspect
public class MyAspectJ {
//@Before代表在执行方法之前执行增强代码
@Before("execution(* com.study.dog.Dog.*(..))")
public void before1() {
System.out.println("饲养员叫你你猜能动");
} }

5编写配置文件

<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here --> <!-- 配置注解bean所在的包 -->
<context:annotation-config/>
<context:component-scan base-package="com.study.spring.d_advisor"></context:component-scan>
<!-- 打开自动代理 -->
<aop:aspectj-autoproxy/> <!-- 被代理对象 -->
<bean id="Dog" class="com.study.dog.Dog"></bean>
<!-- 切面 -->
<bean id="MyAspectJ" class="com.study.dog.MyAspectJ"></bean> </beans>

6.编写测试类

 import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; //完成配置文件的加载
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class AspectJTest {
// 得到dog对象
@Autowired
@Qualifier("Dog")
private Dog dog; @Test
public void Demo1() {
dog.eat();
dog.run();
dog.jump();
}
/*
* 输出结果:
* 饲养员叫你你猜能动
* 狗能吃
* 饲养员叫你你猜能动
* 狗会跑
* 饲养员叫你你猜能动
* 狗会跳
*/
}

总结:上面是一个最简单的AspectJ的AOP,我们这样就可以通过输入一个”饲养员叫你你猜能动",就可以在多个方法中存在,在以后开发非常需要

那么下来来说一些非常重要的干货!

 AspectJ表达式:
    语法:execution(表达式) 通过execution函数,可以定义切点的方法切入

      execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)      

例如

execution(public * *(..))                             匹配所有类public方法

execution(* cn.study.dao..*(..))                  匹配指定包下所有类方法,不包含子包

     execution(* cn.study.dao..*(..))                  ..*表示包、子孙包下所有类

     execution(* cn.study.service.UserService.*(..))  匹配指定类所有方法

     execution(* cn.study.dao.GenericDAO+.*(..))   匹配实现特定接口所有类方法

     execution(* save*(..))                                     匹配所有save开头的方法

    AspectJ增强
    @Before 前置通知,相当于BeforeAdvice
    @AfterReturning 后置通知,相当于AfterReturningAdvice
    @Around 环绕通知,相当于MethodInterceptor
    @AfterThrowing抛出通知,相当于ThrowAdvice
    @After 最终final通知,不管是否异常,该通知都会执行
    @DeclareParents 引介通知,相当于IntroductionInterceptor (不要求掌握)

那现在我们通过上面的列子,来全面贯彻上面的干货!

对上面MyAspectJ的进行全面增强:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
//@Aspect声明当前类是一个切面
@Aspect
public class MyAspectJ { //@Before代表在执行方法之前执行增强代码
@Before("execution(* com.study.dog.Dog.run(..))")
public void before(JoinPoint joinPoint){
System.out.println("前置增强...."+joinPoint);
}
//后置通知
@AfterReturning (value="execution(* com.study.dog.Dog.jump(..))",returning="returnVal")
public void afterReturin(Object returnVal){
System.out.println("后置增强....方法的返回值:"+returnVal);
}
//环绕通知
@Around(value="MyAspectJ.myPointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("环绕前增强....");
Object obj = proceedingJoinPoint.proceed();
System.out.println("环绕后增强....");
return obj;
}
//抛出通知
@AfterThrowing(value="MyAspectJ.myPointcut()",throwing="e")
public void afterThrowing(Throwable e){
System.out.println("不好了 出异常了!!!"+e.getMessage());
} //最终final通知,不管是否异常,该通知都会执行
@After("MyAspectJ.myPointcut()")
public void after(){
System.out.println("最终通知...");
}
//切点的定义
@Pointcut("execution(* com.study.dog.Dog.eat(..))")
private void myPointcut(){}
}

编写测试类AspectJTest   和上面一点不变

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; //完成配置文件的加载
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class AspectJTest {
// 得到dog对象
@Autowired
@Qualifier("Dog")
private Dog dog; @Test
public void Demo1() {
dog.eat();
dog.run();
dog.jump();
} }

运行结果:

通过这个例子,相信大家对于AspectJ的AOP有了一定的了解了。

最后补充一个面试题:

Advisor和Aspect的区别?
        Advisor:Spring传统意义上的切面:支持一个切点和一个通知的组合.
        Aspect:可以支持多个切点和多个通知的组合.

这篇文章就讲到这里,有不足之处,欢迎大家指出,谢谢!

Spring框架(6)---AspectJ实现AOP的更多相关文章

  1. Spring框架IOC容器和AOP解析 非常 有用

    Spring框架IOC容器和AOP解析   主要分析点: 一.Spring开源框架的简介  二.Spring下IOC容器和DI(依赖注入Dependency injection) 三.Spring下面 ...

  2. spring框架之AspectJ的XML方式完成AOP的开发

    1. 步骤一:创建JavaWEB项目,引入具体的开发的jar包 * 先引入Spring框架开发的基本开发包 * 再引入Spring框架的AOP的开发包 * spring的传统AOP的开发的包 * sp ...

  3. Spring框架的基本使用(AOP部分)

    AOP,Aspect Oriented Programming,意为面向切面编程,是通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术.AOP采取横向抽取机制,取代了传统纵向继承体系重复 ...

  4. Java开发工程师(Web方向) - 04.Spring框架 - 第3章.AOP技术

    第3章--AOP技术 Spring框架 - AOP概述 笔记https://my.oschina.net/hava/blog/758873Spring框架 - AOP使用 笔记https://my.o ...

  5. 深入学习Spring框架(三)- AOP面向切面

    1.什么是AOP? AOP为 Aspect Oriented Programming 的缩写,即面向切面编程, 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术..AOP是OOP的延续, ...

  6. Spring框架之IoC和AOP

    Spring框架简介: 2003年2月,Spring框架正式成为一个开源项目,并发布于SourceForge中.致力于Java EE应用的各种解决方案,而并不是仅仅专注于某一层的方案,是企业应用开发的 ...

  7. Spring 框架基础(04):AOP切面编程概念,几种实现方式演示

    本文源码:GitHub·点这里 || GitEE·点这里 一.AOP基础简介 1.切面编程简介 AOP全称:Aspect Oriented Programming,面向切面编程.通过预编译方式和运行期 ...

  8. Spring框架IOC容器和AOP解析

    主要分析点: 一.Spring开源框架的简介  二.Spring下IOC容器和DI(依赖注入Dependency injection) 三.Spring下面向切面编程(AOP)和事务管理配置  一.S ...

  9. Spring框架(四)AOP面向切面编程

    一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnbl ...

随机推荐

  1. Angular - - $q 承诺与延迟

    $q 一个帮助处理异步执行函数的服务.当他们做完处理时,使用它们的返回值(或异常). 受 Kris Kowa’s Q 的启发,这是一个实现promise/deferred对象的启用. $q的两种方式- ...

  2. Java Me-List控件的用法案例

    /** * Java Me-List控件的用法案例 */package com.xushouwei.cn; import java.io.IOException;import javax.microe ...

  3. js模块化开发——前端模块化

    在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可:如今CPU.浏览器性能得到了极大的提升,很多页面逻辑迁移到了客 户端(表单验证等),随着web2.0时代的到来,Ajax技术 ...

  4. V8引擎嵌入指南

    如果已读过V8编程入门那你已经熟悉了如句柄(handle).作用域(scope)和上下文(context)之类的关键概念,以及如何将V8引擎作为一个独立的虚拟机来使用.本文将进一步讨论这些概念,并介绍 ...

  5. pytho查找斐波那契序列中的值

    ''' 实现斐波那契序列,查找其中第N个数的值 ''' def FeiBSequence(list,N): length=len(list); i=0; while i<length: if N ...

  6. .NET操作RabbitMQ组件EasyNetQ使用中文简版文档。

    本文出自EasyNetQ官方文档,内容为自己理解加翻译.文档地址:https://github.com/EasyNetQ/EasyNetQ/wiki/Quick-Start EasyNetQ简介 Ea ...

  7. POJ1556(割点)

    SPF Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 8114   Accepted: 3716 Description C ...

  8. 微信小程序教程(第二篇)

    如何注册接入小程序及搭建开发环境 小程序接入流程 注册 主要分为注册邮箱与信息登记. 需要重新申请一个新的微信公众帐号,不能使用服务号.订阅号或企业号使用的公众帐号 (微信公众帐号分为四种类型:订阅号 ...

  9. Git学习之路(4)- 撤销操作、删除文件和恢复文件

    ▓▓▓▓▓▓ 大致介绍 经过前面的学习(小白学Git)已经建立了版本库,并上传了文件,这次来学习对这些文件进行基本的操作,即: ◆ 撤销操作 ◆ 删除文件 ◆ 恢复文件 我在此之前,已经将三个文件提交 ...

  10. 蓝桥网试题 java 基础练习 01字串

    ---------------------------------------------------------------------- 还括以 0.0 --------------------- ...