spring aop advice
1.前置通知(BeforeAdvice):
- import java.lang.reflect.Method;
- import org.springframework.aop.MethodBeforeAdvice;
- public class HelloBeforeAdvice implements MethodBeforeAdvice{
- public void before(Method method, Object[] args, Object target) throws Throwable {
- System.out.println("do something before some method");
- }
- }
如果出现 The hierarchy of the type HelloBeforeAdvice is inconsistent错误 , 是缺少相关的jar或者jdk环境不对。
2.后置通知(AfterAdvice)
- import java.lang.reflect.Method;
- import org.springframework.aop.AfterReturningAdvice;
- public class HelloAfterAdvice implements AfterReturningAdvice {
- public void afterReturning(Object result, Method method, Object[] args, Object target) throws Throwable {
- System.out.println("do something after the method");
- }
- }
3. Test client
- import org.springframework.aop.framework.ProxyFactory;
- public class TestClient {
- public static void main(String[] args) {
- ProxyFactory proxyFactory = new ProxyFactory();//创建代理工厂
- proxyFactory.setTarget(new HelloImpl());
- proxyFactory.addAdvice(new HelloBeforeAdvice());
- proxyFactory.addAdvice(new HelloAfterAdvice());
- Hello helloProxy = (Hello) proxyFactory.getProxy();
- System.out.println(helloProxy.sayHello("zhangsan"));
- }
- }
- ----------------------------
public class HelloImpl implements Hello {- public String sayHello(String str) {
System.out.println("hello>>>"+str);
return "hello>>>"+str;
}
}
4. 环绕通知(AroundAdvice)
- //aop联盟提供的接口
- import org.aopalliance.intercept.MethodInterceptor;
- import org.aopalliance.intercept.MethodInvocation;
- public class HelloAroundAdvice implements MethodInterceptor {
- public Object invoke(MethodInvocation invocation) throws Throwable {
- System.out.println("before method>>>");
- Object result = invocation.proceed();
- System.out.println("after method>>");
- return result;
- }
- }
5. spring 配置文件方式
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
- xmlns:util="http://www.springframework.org/schema/util" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
- xmlns:cache="http://www.springframework.org/schema/cache"
- xsi:schemaLocation="
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx.xsd
- http://www.springframework.org/schema/jdbc
- http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
- http://www.springframework.org/schema/cache
- http://www.springframework.org/schema/cache/spring-cache.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop.xsd
- http://www.springframework.org/schema/util
- http://www.springframework.org/schema/util/spring-util.xsd">
- <!-- 自动扫描ppms包 ,将带有注解的类 纳入spring容器管理 -->
- <context:component-scan base-package="com.cdv.ppms"></context:component-scan>
- <bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="interfaces" value="com.cdv.ppms.Hello"/><!-- 需要代理的接口 -->
- <property name="target" ref="helloImpl"/><!-- 接口实现类 , 此处需要是ref 否则object is not an instance of declaring class-->
- <property name="interceptorNames"><!-- 拦截器 名称-->
- <list>
- <value>helloAroundAdvice</value>
- </list>
- </property>
- </bean>
- <bean id="helloImpl" class="com.cdv.ppms.HelloImpl"></bean>
- </beans>
- import org.springframework.stereotype.Component;
- @Component
- public class HelloImpl implements Hello {
- //...
- }
- @Component
- public class HelloAroundAdvice implements MethodInterceptor {
- //....
- }
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class TestXMLClient {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- Hello hello = (Hello) context.getBean("helloProxy");
- hello.sayHello("test xml");
- }
- }
6. 抛出通知(ThrowAdvice)
- import java.lang.reflect.Method;
- import org.springframework.aop.ThrowsAdvice;
- import org.springframework.stereotype.Component;
- @Component
- public class HelloThrowAdvice implements ThrowsAdvice{
- public void afterThrowing(Method method, Object[] args, Object target, Exception e){
- System.out.println("-------------------Throw Exception------------------------");
- System.out.println("target class>>"+target.getClass().getName());
- System.out.println("method class>>" + method.getName());
- System.out.println("exception message>>"+e.getMessage());
- System.out.println("-------------------Throw Exception------------------------");
- }
- }
- <bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="interfaces" value="com.cdv.ppms.Hello"/><!-- 需要代理的接口 -->
- <property name="target" ref="helloImpl"/><!-- 接口实现类 -->
- <property name="interceptorNames"><!-- 拦截器 名称-->
- <list>
- <value>helloAroundAdvice</value>
- <value>testThrowAdvice</value>
- </list>
- </property>
- </bean>
- import org.springframework.stereotype.Component;
- @Component
- public class HelloImpl implements Hello {
- public String sayHello(String str) {
- System.out.println("hello>>>"+str);
- throw new RuntimeException("error>>");//加入异常以便测试
- }
- }
7. 引入通知(Introduction Advice)
对方法的增强叫织入(Weaving),对类的增强叫引入(Introduction)
- import org.aopalliance.intercept.MethodInvocation;
- import org.springframework.aop.support.DelegatingIntroductionInterceptor;
- import org.springframework.stereotype.Component;
- @Component
- public class HelloIntroAdvice extends DelegatingIntroductionInterceptor implements Apology {
- /**
- *
- */
- private static final long serialVersionUID = -3328637206414010549L;
- public Object invoke(MethodInvocation invocation) throws Throwable{
- return super.invoke(invocation);
- }
- public void saySorry(String str) {
- System.out.println("introduction advice>>>"+str);
- }
- }
- <bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="interfaces" value="com.cdv.ppms.Apology"/><!-- 需要代理的接口 -->
- <property name="target" ref="helloImpl"/><!-- 接口实现类 -->
- <property name="interceptorNames"><!-- 拦截器 名称-->
- <list>
- <value>helloAroundAdvice</value>
- <value>helloThrowAdvice</value>
- <value>helloIntroAdvice</value>
- </list>
- </property>
- <property name="proxyTargetClass" value="true"></property><!--代理目标类, 默认false代理接口-->
- </bean>
- <bean id="helloImpl" class="com.cdv.ppms.HelloImpl"></bean>
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class TestXMLClient {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- HelloImpl helloImpl = (HelloImpl) context.getBean("helloProxy");
- helloImpl.sayHello("test xml");
- Apology apology = (Apology) helloImpl;//将目标类向上强制转型为Apology接口, 这时引入通知给我们带来的特性, 也就是“接口动态实现”功能
- apology.saySorry("zhangsan");
- }
- }
8. 切面(Advisor)
切面(Advisor)封装了通知(Advice)和切点(Pointcut)
- import org.springframework.stereotype.Component;
- @Component
- public class HelloImpl implements Hello {
- public String sayHello(String str) {
- System.out.println("hello>>>"+str);
- return str;
- }
- public void advisorOne(String name){
- System.out.println("advisor one>>>"+name);
- }
- public void advisorTwo(String name){
- System.out.println("advisor two>>"+name);
- }
- }
在代理类中新增以advisor开头的方法,对其进行拦截
- <context:component-scan base-package="com.cdv.ppms"></context:component-scan>
- <!--定义切面-->
- <bean id="helloAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
- <property name="advice" ref="helloAroundAdvice"/>
- <property name="pattern" value="com.cdv.ppms.HelloImpl.advisor.*"></property><!-- 切点 (正则表达式) -->
- </bean>
- <bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="target" ref="helloImpl"/><!-- 接口实现类 -->
- <property name="interceptorNames" value="helloAdvisor"/>
- <property name="proxyTargetClass" value="true"></property>
- </bean>
- <bean id="helloImpl" class="com.cdv.ppms.HelloImpl"></bean>
- <bean id="helloAroundAdvice" class="com.cdv.ppms.HelloAroundAdvice"></bean>
- import org.aopalliance.intercept.MethodInterceptor;
- import org.aopalliance.intercept.MethodInvocation;
- import org.springframework.stereotype.Component;
- @Component
- public class HelloAroundAdvice implements MethodInterceptor {
- public Object invoke(MethodInvocation invocation) throws Throwable {
- System.out.println("before method>>>");
- Object result = invocation.proceed();
- System.out.println("after method>>");
- return result;
- }
- }
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class TestXMLClient {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- HelloImpl helloImpl = (HelloImpl) context.getBean("helloProxy");
- helloImpl.advisorOne("11111111");
- helloImpl.advisorTwo("2222222222");
- }
- }
- -------------around包了两层, 有问题-------------------------------------------
- before method>>>
- before method>>>
- advisor one>>>11111111
- after method>>
- after method>>
- before method>>>
- before method>>>
- advisor two>>2222222222
- after method>>
- after method>>
- ------------------------
随着项目的扩大, 上述的代理配置会越来越多。
9. 自动代理(扫描bean名称)
定义BeanNameAutoProxyCreator,该bean是个bean后处理器,无需被引用,因此没有id属性
- <context:component-scan base-package="com.cdv.ppms"></context:component-scan>
- <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
- <property name="beanNames" value="*Impl"/><!--对以Impl结尾的类进行处理-->
- <property name="interceptorNames" value="helloAroundAdvice"/>
- <property name="optimize" value="true"/>
- </bean>
- <bean id="helloImpl" class="com.cdv.ppms.HelloImpl"></bean>
- <bean id="helloAroundAdvice" class="com.cdv.ppms.HelloAroundAdvice"></bean>
测试
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class TestXMLClient {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- HelloImpl helloImpl = (HelloImpl) context.getBean("helloImpl");
- helloImpl.advisorOne("11111111");//
- helloImpl.advisorTwo("2222222222");
- helloImpl.sayHello("zhangwuji");
- }
- }
10. 自动代理(扫描切面配置)
代理将由DefaultAdvisorAutoProxyCreator自动生成,这个类可以扫描所有的切面类
- <context:component-scan base-package="com.cdv.ppms"></context:component-scan>
- <bean id="helloAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
- <property name="advice" ref="helloAroundAdvice"/>
- <property name="pattern" value="com.cdv.ppms.HelloImpl.advisor.*"/>
- </bean>
- <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
- <property name="optimize" value="true"/>
- </bean>
- <bean id="helloImpl" class="com.cdv.ppms.HelloImpl"></bean>
- <bean id="helloAroundAdvice" class="com.cdv.ppms.HelloAroundAdvice"></bean>
测试
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class TestXMLClient {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- HelloImpl helloImpl = (HelloImpl) context.getBean("helloImpl");
- helloImpl.advisorOne("11111111");
- helloImpl.advisorTwo("2222222222");
- helloImpl.sayHello("zhangwuji");
- }
- }
- //只有符合advisor开头的方法才会被代理
这样在spring的配置中会存在大量的切面配置(想拦截指定注解的方法,就必须拓展DefaultPointcutAdvisor类,自定义一个切面类)。
11. Spring & AspectJ
11-1 基于注解 :通过execution()表达式 拦截方法
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Aspect;
- import org.springframework.stereotype.Component;
- @Aspect
- @Component
- public class HelloAspect {
- @Around("execution(* com.cdv.ppms.HelloImpl.*(..))")//切点表达式
- public Object around(ProceedingJoinPoint pjp) throws Throwable{
- before();
- Object result = pjp.proceed();
- after();
- return result;
- }
- private void after() {
- System.out.println("hey,, after.");
- }
- private void before() {
- System.out.println("hey,, before");
- }
- }
切点表达式
execution()表示拦截的方法, 挂号中定义拦截的规则
上面第一个*表示返回任意类型
第二个*表示HelloImpl类中的任意方法
..表示任意类型参数
- <context:component-scan base-package="com.cdv.ppms"></context:component-scan>
- <aop:aspectj-autoproxy proxy-target-class="true"/><!-- 默认值为false只能代理接口,当为true时才能代理目标类 -->
- <bean id="helloImpl" class="com.cdv.ppms.HelloImpl"></bean>
test
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class TestXMLClient {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- HelloImpl helloImpl = (HelloImpl) context.getBean("helloImpl");
- helloImpl.advisorOne("11111111");
- helloImpl.advisorTwo("2222222222");
- helloImpl.sayHello("zhangwuji");
- }
- }
11-2 基于注解 通过AspectJ @annotation表达式拦截方法
自定义注解
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface MyTag {
- }
更改aspect类的切点表达式
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Aspect;
- import org.springframework.stereotype.Component;
- @Aspect
- @Component
- public class HelloAspect {
- @Around("@annotation(com.cdv.ppms.MyTag)")
- public Object around(ProceedingJoinPoint pjp) throws Throwable{
- before();
- Object result = pjp.proceed();
- after();
- return result;
- }
- private void after() {
- System.out.println("hey,, after.");
- }
- private void before() {
- System.out.println("hey,, before");
- }
- }
该注解可以标注在方法上,运行时生效
- import org.springframework.stereotype.Component;
- @Component
- public class HelloImpl implements Hello {
- public String sayHello(String str) {
- System.out.println("hello>>>"+str);
- return str;
- }
- @MyTag
- public void advisorOne(String name){
- System.out.println("advisor one>>>"+name);
- }
- public void advisorTwo(String name){
- System.out.println("advisor two>>"+name);
- }
- }
配置
- <context:component-scan base-package="com.cdv.ppms"></context:component-scan>
- <bean id="helloImpl" class="com.cdv.ppms.HelloImpl"></bean>
测试
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class TestXMLClient {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- HelloImpl helloImpl = (HelloImpl) context.getBean("helloImpl");
- helloImpl.advisorOne("11111111");
- helloImpl.advisorTwo("2222222222");
- helloImpl.sayHello("zhangwuji");
- }
- }
其他几个注解
@Before @After @AfterThrowing @DeclareParents引入通知 AfterReturning(返回后通知,在方法结束后执行)
11-3 引入通知
Aspect类
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.DeclareParents;
- import org.springframework.stereotype.Component;
- @Aspect
- @Component
- public class HelloAspect {
- //something need to do
- @DeclareParents(value="com.cdv.ppms.HelloImpl",defaultImpl=com.cdv.ppms.ApologyImpl.class)
- private Apology apology;
- }
接口实现类
- public class ApologyImpl implements Apology {
- public void saySorry(String str) {
- System.out.println("apologyImpl>>>"+str);
- }
- }
配置
- <context:component-scan base-package="com.cdv.ppms"></context:component-scan>
- <bean id="helloImpl" class="com.cdv.ppms.HelloImpl"></bean>
测试
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class TestXMLClient {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- HelloImpl helloImpl = (HelloImpl) context.getBean("helloImpl");
- helloImpl.sayHello("zhangwuji");
- Apology apology = (Apology) helloImpl;
- apology.saySorry("hahahahah");
- }
- }
spring aop advice的更多相关文章
- spring AOP advice 类型 和 通用的切点的配置方式
spring aop advice的类型: 1.前置通知(before advice) 2.返回后通知(after returning advice) 3.抛出异常后通知(after throwing ...
- Spring AOP Example – Advice
Spring AOP + AspectJ Using AspectJ is more flexible and powerful. Spring AOP (Aspect-oriented progra ...
- Spring AOP Example – Pointcut , Advisor
In last Spring AOP advice examples, the entire methods of a class are intercepted automatically. But ...
- 框架源码系列三:手写Spring AOP(AOP分析、AOP概念学习、切面实现、织入实现)
一.AOP分析 问题1:AOP是什么? Aspect Oriented Programming 面向切面编程,在不改变类的代码的情况下,对类方法进行功能增强. 问题2:我们需要做什么? 在我们的框架中 ...
- Spring -- aop(面向切面编程),前置&后置&环绕&抛异常通知,引入通知,自动代理
1.概要 aop:面向方面编程.不改变源代码,还为类增加新的功能.(代理) 切面:实现的交叉功能. 通知:切面的实际实现(通知要做什么,怎么做). 连接点:应用程序执行过程期间,可以插入切面的地点. ...
- Spring Aop(十四)——Aop自动创建代理对象的原理
转发地址:https://www.iteye.com/blog/elim-2398725 Aop自动创建代理对象的原理 我们在使用Spring Aop时,通常Spring会自动为我们创建目标bean的 ...
- Spring Aop(十)——编程式的Pointcut
转发地址:https://www.iteye.com/blog/elim-2396526 编程式的Pointcut 除了可以通过注解和Xml配置定义Pointcut之外,其实我们还可以通过程序来定义P ...
- Spring Aop(九)——基于正则表达式的Pointcut
转发地址:https://www.iteye.com/blog/elim-2396525 基于正则表达式的Pointcut JdkRegexpMethodPointcut Spring官方为我们提供了 ...
- Spring Aop(八)——advisor标签
转发地址:https://www.iteye.com/blog/elim-2396274 8 advisor标签 advisor标签是需要定义在aspect标签里面的,其作用与aspect类似,可以简 ...
随机推荐
- smdkv210
参考:http://code.google.com/p/libyuv/issues/detail?id=295 ******************************************** ...
- A successful Git branching model
这个模型比较全,收藏一下,原文: http://nvie.com/posts/a-successful-git-branching-model/ 关于这个模型中的hotfix只适应最新的Release ...
- C# 开发者代码审查清单【转】
这是为C#开发者准备的通用性代码审查清单,可以当做开发过程中的参考.这是为了确保在编码过程中,大部分通用编码指导原则都能注意到.对于新手和缺乏经验(0到3年工作经验)的开发者,参考这份清单编码会很帮助 ...
- 使用UIKit制作卡牌游戏(一)ios游戏篇
转自朋友Tommy 的翻译,自己只翻译了第三篇教程. 译者: Tommy | 原文作者: Matthijs Hollemans写于2012/06/29 原文地址: http://www.raywend ...
- 64bit ubuntu 安装32bit的软件
在64bit的系统上安装32bit的软件时,会提示: file not found or no such file. 此时只需要安装 sudo apt-get install libc6-dev-i3 ...
- Legolas工业自动化平台入门(一)搭建应用
前两篇给大家介绍了TWaver家族的新面孔--Legolas工业自动化平台,通过两个应用案例钻井平台工程用车和水源地监控系统,相信大家对Legolas已经有了一定程度的了解.这几篇文章,我们会逐步介绍 ...
- IBM X3650 M4服务器安装centos找不到硬盘的解决方法
IBM X3650 M4是IBM新的2U的服务器,IBM服务器以高稳定性和卓越的性能一直领先其他的服务器品牌成为全球第一.但是我们在用IBM的最新版9.4引导盘引导的时候,里面选项只有windows ...
- left join on
问题: select * from A left join f on e.cust=f.account_id where f.status='0' 与 select * from A left jo ...
- DalekJS – 基于 JavaScript 实现跨浏览器的自动化测试
在 Web 项目中,浏览器兼容以及跨浏览器测试是最重要的也是最费劲的工作.DalekJS 是一个基于 JavaScript(或 Node.js) 的免费和开源的自动化测试接口.它能够同时运行测试一组流 ...
- [C] static和extern的作用
static: 当用于函数定义或者代码块之外的变量声明时,static关键字用于修改标识符的链接属性,从external改为internal. 当用于代码块内部的变量声明时,static关键字用于修改 ...