AOP之基于AspectJ注解总结与案例
林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka
Spring除了支持Schema方式配置AOP,还支持注解方式:使用@AspectJ风格的切面声明。导入需要的包:aspectjweaver.jar、aopalliance-1.0.jar
本文工程免费下载
一、基本使用方法
1.1、启用对@AspectJ的支持
Spring默认不支持@AspectJ风格的切面声明,为了支持需要使用如下配置:
<!-- 启动@AspectJ支持 --><!-- proxy-target-class默认"false",更改为"ture"使用CGLib动态代理 --> <aop:aspectj-autoproxy proxy-target-class="false"/>
这样Spring就能发现@AspectJ风格的切面并且将切面应用到目标对象。
1.2、 声明切面
@AspectJ风格的声明切面非常简单,使用@Aspect注解进行声明:
@Aspect
public class AdivceMethod {
然后将该切面在配置文件中声明为Bean后,Spring就能自动识别并进行AOP方面的配置:
<bean id="aspect" class="……AdivceMethod"/>
或者直接使用元注解的方法:
@Component
@Aspect
public class AdivceMethod {
1.3、 声明切入点
@AspectJ风格的命名切入点使用org.aspectj.lang.annotation包下的@Pointcut+方法(方法必须是返回void类型)实现。
@Pointcut(value="切入点表达式", argNames = "参数名列表")public void pointcutName(……) {}
value:指定切入点表达式;
argNames:指定命名切入点方法参数列表参数名字,可以有多个用“,”分隔,这些参数将传递给通知方法同名的参数,同时比如切入点表达式“args(param)”将匹配参数类型为命名切入点方法同名参数指定的参数类型。
pointcutName:切入点名字,可以使用该名字进行引用该切入点表达式。
@Pointcut(value="execution(* cn.javass..*.sayAdvisorBefore(..)) && args(param)", argNames = "param") public void beforePointcut(String param) {}
定义了一个切入点,名字为“beforePointcut”,该切入点将匹配目标方法的第一个参数类型为通知方法实现中参数名为“param”的参数类型。
二、声明通知
@AspectJ风格的声明通知也支持5种通知类型:
2.1、前置通知:使用org.aspectj.lang.annotation 包下的@Before注解声明;
@Before(value = "切入点表达式或命名切入点", argNames = "参数列表参数名")
value:指定切入点表达式或命名切入点;
argNames:与Schema方式配置中的同义。
接下来示例一下吧:
1、定义接口和实现,在此我们就使用Schema风格时的定义;
2、定义切面:
3、定义切入点:
4、定义通知:
2.2、后置返回通知:使用org.aspectj.lang.annotation 包下的@AfterReturning注解声明;
@AfterReturning( value="切入点表达式或命名切入点", pointcut="切入点表达式或命名切入点", argNames="参数列表参数名", returning="返回值对应参数名")
value:指定切入点表达式或命名切入点;
pointcut:同样是指定切入点表达式或命名切入点,如果指定了将覆盖value属性指定的,pointcut具有高优先级;
argNames:与Schema方式配置中的同义;
returning:与Schema方式配置中的同义。
2.3、后置异常通知:使用org.aspectj.lang.annotation 包下的@AfterThrowing注解声明;
@AfterThrowing (
value="切入点表达式或命名切入点",
pointcut="切入点表达式或命名切入点",
argNames="参数列表参数名",
throwing="异常对应参数名")
value:指定切入点表达式或命名切入点;
pointcut:同样是指定切入点表达式或命名切入点,如果指定了将覆盖value属性指定的,pointcut具有高优先级;
argNames:与Schema方式配置中的同义;
throwing:与Schema方式配置中的同义。
其中测试代码与Schema方式几乎一样,在此就不演示了,如果需要请参考AopTest.java中的testAnnotationAfterThrowingAdvice测试方法。
2.4、后置最终通知:使用org.aspectj.lang.annotation 包下的@After注解声明;
@After ( value="切入点表达式或命名切入点", argNames="参数列表参数名")
value:指定切入点表达式或命名切入点;
argNames:与Schema方式配置中的同义;
2.5、环绕通知:使用org.aspectj.lang.annotation 包下的@Around注解声明;
@Around ( value="切入点表达式或命名切入点", argNames="参数列表参数名")
value:指定切入点表达式或命名切入点;
argNames:与Schema方式配置中的同义;
2.6 引入
@AspectJ风格的引入声明在切面中使用org.aspectj.lang.annotation包下的@DeclareParents声明:
@DeclareParents( value=" AspectJ语法类型表达式", defaultImpl=引入接口的默认实现类) private Interface interface;
value:匹配需要引入接口的目标对象的AspectJ语法类型表达式;与Schema方式中的types-matching属性同义;
private Interface interface:指定需要引入的接口;
defaultImpl:指定引入接口的默认实现类,没有与Schema方式中的delegate-ref属性同义的定义方式;
三、使用范例
整个工程目录如下:
本文工程免费下载
记得导入包:aopalliance-1.0.jar+aspectjweaver.jar+commons-logging-1.2.jar+spring
1、首先新建一个人的接口类:
package com.mucfu.aspectj;
/**
*功能 人的接口类
*作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka)
*时间 2015.4.27
*/
public interface Person {public void eatBreakfast();public void eatLunch();public void eatSupper();public String drink(String name);}
2、来个baby的实现类:
package com.mucfu.aspectj;import org.springframework.stereotype.Component;/**
*功能 人的实现类
*作者 林炳文(ling20081005@126.com 博客:http://blog.csdn.net/evankaka)
*时间 2015.4.27
*/
@Component
public class BabyPerson implements Person{@Overridepublic void eatBreakfast() {System.out.println("小Baby正在吃早餐");}@Overridepublic void eatLunch() {System.out.println("小Baby正在吃午餐");}@Overridepublic void eatSupper() {System.out.println("小Baby正在吃晚餐");}@Overridepublic String drink(String name) {return "小Baby在喝:"+name;}}
3、然后后就是对Bayby吃饭的函数进行各种增强
package com.mucfu.aspectj;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;@Component
@Aspect
public class AdivceMethod {@Before("execution(* com.mucfu.aspectj.BabyPerson.*(..))")// 匹配BabyPerson类所有的方法,注意*和com之间有个空格public void beforeEat() {System.out.println("-------------------这里是前置增强,吃饭之前先洗小手!--------------------");}@After("execution(* eatLunch(..))")// 匹配该工程下所有的eatLunch方法public void afterEat() {System.out.println("-------------------这里是后置增强,午饭吃完要睡午觉!--------------------");}@Around("execution(* com.mucfu.aspectj.BabyPerson.eatSupper())")// 匹配该工程下BabyPerson的eatLunch方法public Object aroundEat(ProceedingJoinPoint pjp) throws Throwable {System.out.println("-------------------这里是环绕增强,吃晚饭前先玩一玩!-------------------");Object retVal = pjp.proceed();System.out.println("-------------------这里是环绕增强,晚饭吃完后要得睡觉了!-------------------");return retVal;}@AfterReturning(returning="rvt",pointcut="execution(* com.mucfu.aspectj.BabyPerson.drink(..))")public void log(Object rvt) {System.out.println("-------------------这里是AfterReturning增强-------------------");System.out.println("获取小Baby正在喝的饮料"+rvt);System.out.println("记录每天喝的饮料容量");}}
4、新建一个beans.xml,内容如下:
<?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:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"><!-- 指定自动搜索bean组件、自动搜索切面类 --><context:component-scan base-package="com.mucfu"/><!-- 启动@AspectJ支持 --><!-- proxy-target-class默认"false",更改为"ture"使用CGLib动态代理 --> <aop:aspectj-autoproxy proxy-target-class="false"/></beans>
5、最后来测试
package com.mucfu.aspectj;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");Person person=(Person)context.getBean("babyPerson");person.eatBreakfast();System.out.println("===================================================");person.eatLunch();System.out.println("===================================================");person.eatSupper();System.out.println("===================================================");person.drink("可乐");System.out.println("===================================================");}}
输出结果:
五月 19, 2015 10:14:51 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@19855ed: startup date [Tue May 19 10:14:51 CST 2015]; root of context hierarchy
五月 19, 2015 10:14:51 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans.xml]
五月 19, 2015 10:14:52 上午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1048104: defining beans [adivceMethod,babyPerson,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
-------------------这里是前置增强,吃饭之前先洗小手!--------------------
小Baby正在吃早餐
===================================================
-------------------这里是前置增强,吃饭之前先洗小手!--------------------
小Baby正在吃午餐
-------------------这里是后置增强,午饭吃完要睡午觉!--------------------
===================================================
-------------------这里是环绕增强,吃晚饭前先玩一玩!-------------------
-------------------这里是前置增强,吃饭之前先洗小手!--------------------
小Baby正在吃晚餐
-------------------这里是环绕增强,晚饭吃完后要得睡觉了!-------------------
===================================================
-------------------这里是前置增强,吃饭之前先洗小手!--------------------
-------------------这里是AfterReturning增强-------------------
获取小Baby正在喝的饮料小Baby在喝:可乐
记录每天喝的饮料容量
===================================================
本文工程免费下载
林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka
AOP之基于AspectJ注解总结与案例相关推荐
- Spring Aop(四)——基于Aspectj注解的Advice介绍
4 基于Aspectj注解的Advice介绍 之前介绍过,Advice一共有五种类型,分别是before.after return.after throwing.after(finally)和arou ...
- Spring Aop实例之AspectJ注解配置
上篇博文<Spring Aop实例之xml配置>中,讲解了xml配置方式,今天来说说AspectJ注解方式去配置spring aop. 依旧采用的jdk代理,接口和实现类代码请参考上篇博文 ...
- Spring AOP技术(基于AspectJ)的Annotation开发
Spring AOP技术(基于AspectJ)的Annotation开发 @(Spring)[aop, spring, xml, Spring, annotation, aspectJ] Spring ...
- Spring AOP技术(基于AspectJ)的XML开发
Spring AOP技术(基于AspectJ)的XML开发 @(Spring)[aop, spring, xml, Spring, annotation, aspectJ] Spring AOP技术基 ...
- 面向切面(AOP)之Spring接口方式 schema配置方式 aspectj注解方式
一.初识AOP 关于AOP的学习可以参看帮助文档:spring-3.2.0.M2\docs\reference\html目录下index.html的相关章节 1.AOP:Aspect-O ...
- 基于@AspectJ配置Spring AOP之一--转
原文地址:http://tech.it168.com/j/2007-08-30/200708302209432.shtml 概述 在低版本Spring中定义一个切面是比较麻烦的,需要实现特定的接口,并 ...
- Spring基于AspectJ实现AOP操作
基于AspectJ实现AOP操作 准备工作 在项目工程里面引入 AOP 相关依赖. 如果是maven项目,使用pom.xml代替引入jar包的过程(注意) 学会使用切入点表达式 AOP 操作(Aspe ...
- 使用AspectJ注解技术实现AOP功能
AspectJ是一个面向切面编程的框架,使用AspectJ不需要改动Spring配置文件,就可以实现Spring AOP功能.本篇结合实际案例详细讲述使用AspectJ实现AOP功能.通过本篇的学习, ...
- Spring-aop 基于Aspectj 表达式配置AOP
基于Aspectj 表达式配置AOP(推荐使用) 基于配置文件 1.添加切面对象(aspect对象) 2.把切面对象交给spring 3.配置文件 <?xml version="1.0 ...
- mybatis基于注解的入门案例
mybatis基于注解的入门案例: 把IUserDao.xml移除,在dao接口的方法上使用@Select注解,并且指定SQL语句 同时需要在SqlMa ...
最新文章
- 一人一天发两篇Science,配视频揭秘:植物如何在与病菌的斗争中取胜?
- Android开发之旅:环境搭建及HelloWorld
- SpringBoot的配置详解application
- C++#define的用法(含特殊)
- mysql run sql files_如何在Eclipse DTP中運行多個.sql文件
- 使用MeanJS Yeoman Generator
- 如何把一个网页生成一个快捷方式在桌面?_如何打造一个简洁、高效的桌面?
- iPDA“国际智能车联合道路演示”压轴,IEEE IV 2018 圆满落幕!
- Nacos发布0.5.0版本,轻松玩转动态 DNS 服务
- discuz加密解密,可参考下
- Websphere7上发布web程序
- Oracle 角色权限表
- php 或取域名的ip,php如何获取域名IP地址代码函数
- 关于英特尔® 处理器显卡技术
- socket学习之电脑手机通信
- python输入个人所得税计算_python-计算个人所得税
- 财务内部收益率用计算机怎么算,​财务内部收益率怎么算
- java qq登陆 server_java实现QQ互联登录
- fiddler接口基础
- 傅里叶变换、拉普拉斯变换与z变换对比