spring心得8--AOP各种通知案例讲解.doc
来源:互联网 发布:监控软件行为 编辑:程序博客网 时间:2024/05/17 03:50
上一篇博客中已经简单介绍了,这里通过案例详细说明一下aop中各种通知的用法。
先列出后面介绍的JDK动态代理通知(主要区别于cglib代理而言,下面会具体介绍)、静态切入点、正则切入点等都依赖使用的抽象主题(一个接口,可以是多个)、是、真实主题(改接口的实现类)
接口:SayService.java
package www.csdn.spring.proxy.advice;public interface SayService {public void say(String content);public void sayHi();public void sayHello();public void byebye();}
实现类:SayServiceImpl.java
package www.csdn.spring.proxy.advice;public interface SayService {public void say(String content);public void sayHi();public void sayHello();public void byebye();} 实现类:SayServiceImpl.javapackage www.csdn.spring.proxy.advice;public class SayServiceImpl implements SayService{@Overridepublic void say(String content) {System.out.println("say:"+content);//int i=1/0;}@Overridepublic void sayHi() {System.out.println("===sayHi()方法执行了===");}@Overridepublic void sayHello() {System.out.println("===sayHello()方法执行了===");}@Overridepublic void byebye() {System.out.println("===byebye()方法执行了===");}}
1.各种通知的使用,JDK动态代理
前置通知、后置通知、环绕通知、异常通知、引入通知的案例分析,下面注释都有详细解释,这里不再赘述。
spring-advice.xml spring配置文件
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 创建前置通知 --> <bean id="beforeAdvice" class="www.csdn.spring.proxy.advice.BeforeAdvice"/> <!-- 创建后置通知 --> <bean id="afterAdvice" class="www.csdn.spring.proxy.advice.AfterAdvice"/> <!-- 创建环绕通知 --> <bean id="aroundAdvice" class="www.csdn.spring.proxy.advice.AroundAdvice"/> <!-- 创建异常通知 --> <bean id="throwAdvice" class="www.csdn.spring.proxy.advice.ThrowAdvice"/> <!-- 引入通知 --> <bean id="auditableAdvice" class="www.csdn.spring.proxy.advice.AuditableImpl"/> <!-- 真实主题 目标对象 --> <bean id="sayServiceImpl" class="www.csdn.spring.proxy.advice.SayServiceImpl"/> <!-- 配置代理操作 --> <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"> <!--抽象主题 实现接口 --> <property name="proxyInterfaces"> <array> <value>www.csdn.spring.proxy.advice.SayService</value> <value>www.csdn.spring.proxy.advice.Auditable</value> </array> </property> <!-- 目标对象 --> <property name="target"> <ref bean="sayServiceImpl"/> </property> <!-- 织入的通知的名称 --> <property name="interceptorNames"> <array> <value>beforeAdvice</value> <value>afterAdvice</value> <value>aroundAdvice</value> <value>throwAdvice</value> <value>auditableAdvice</value> </array> </property> </bean></beans>
下面是这几个通知具体反映到的类,最关键的是这个几个通知代理类所要继承的接口,不可写错,更不可不写,否则会出错,这些错误将在后期本人一篇spring错误总结的博客中涉及到,敬请期待。
前者通知类:BeforeAdvice.java
package www.csdn.spring.proxy.advice;import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;public class BeforeAdvice implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] args, Object target)throws Throwable {System.out.println("在目标方法执行之前执行........................");// 执行完之后执行exit方法,退出程序//System.exit(0);// 暴露的参数的含义System.out.println("目标方法:" + method.getName());if (args != null && args.length > 0) {for (Object arg : args) {System.out.println("传递的参数值:" + arg);}}System.out.println("目标对象:" + target.getClass());}}后置通知类:AfterAdvice.javapackage www.csdn.spring.proxy.advice;import java.lang.reflect.Method;import org.springframework.aop.AfterReturningAdvice;public class AfterAdvice implements AfterReturningAdvice{@Overridepublic void afterReturning(Object returnValue, Method method,Object[] args, Object target) throws Throwable {System.out.println("在目标方法执行之后执行..............................");}}环绕通知类:AroundAdvice.javapackage www.csdn.spring.proxy.advice;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;public class AroundAdvice implements MethodInterceptor {public void beforeMethod() {System.out.println("around---------------------目标方法之前执行");}public void afterMethod() {System.out.println("around---------------------目标方法之后执行");}@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {Object returnValue = null;beforeMethod();returnValue = invocation.proceed();afterMethod();return returnValue;}}异常通知类:ThrowsAdvice.javapackage www.csdn.spring.proxy.advice;import java.lang.reflect.Method;import org.springframework.aop.ThrowsAdvice;public class ThrowAdvice implements ThrowsAdvice{public void afterThrowing(Method m,Object[] os,Objecttarget,Throwable throwable){System.out.println("出现异常了:"+throwable.getLocalizedMessage());}}
引用通知需要注意是,因为这里spring使用的是jdk动态代理,所以使用引用通知的时候一定先创建一个引用通知的抽象接口,再创建一个引用通知类。
抽象主题 Auditable.java
package www.csdn.spring.proxy.advice;import java.util.Date;public interface Auditable {public void setDate(Date date);public Date getDate();} 引用通知类 AuditableService.javapackage www.csdn.spring.proxy.advice;import java.util.Date;import org.springframework.aop.support.DelegatingIntroductionInterceptor;public class AuditableImpl extends DelegatingIntroductionInterceptor implements Auditable {private Date date;@Overridepublic void setDate(Date date) {this.date = date;}@Overridepublic Date getDate() {return date;}}测试类 AdviceTest.javapackage www.csdn.spring.proxy.advice;import java.util.Date;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class AdviceTest {@Testpublic void testAdvice() {ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-advice.xml");// 不使用代理的时候// context.getBean("sayServiceImpl",SayServiceImpl.class).say("嗨!杨凯!");// 使用代理的时候SayService sayService = context.getBean("proxyFactoryBean", SayService.class);sayService.say("嗨!杨凯!");//引入通知测试Auditable auditable = (Auditable) sayService;auditable.setDate(new Date());System.out.println(auditable.getDate());}}
2.各种通知的使用,cglib代理
spring中的JDK动态代理和cglib代理区别就是:1)在配置文件中的区别,即在配置文件中抽象主键,接口对象配置不同,具体不同详见下面红色部分;主要通过property属性的proxyTargetClass值设置。2)即JDK动态代理和cglib代理的不同,前者基于接口代理,后者基于类代理,所以这里就有了真实主题的不同,即实现类的不同,cglib的真实主题没有实现任何接口。
spring-advices.xml spring配置文件
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 创建前置通知 --> <bean id="beforeAdvice" class="www.csdn.spring.proxy.advice.BeforeAdvice"/> <!-- 创建后置通知 --> <bean id="afterAdvice" class="www.csdn.spring.proxy.advice.AfterAdvice"/> <!-- 创建环绕通知 --> <bean id="aroundAdvice" class="www.csdn.spring.proxy.advice.AroundAdvice"/> <!-- 创建异常通知 --> <bean id="throwAdvice" class="www.csdn.spring.proxy.advice.ThrowAdvice"/> <!-- 真实主题 目标对象 --> <bean id="sayServiceImpls" class="www.csdn.spring.proxy.advice.SayServiceImpls"/> <!-- 配置代理操作 --> <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"> <!--抽象主题 实现接口 --> <!-- 写法一:直接使用代理类,不再去指明是哪个代理类 ;这个时候value的值不管是true或false都其作用--> <property name="proxyTargetClass" value="true"/> <!-- 指明代理类,这时候value必须是true的时候才起作用 ; 使用false会报错:Bean named 'proxyFactoryBean' must be of type [www.csdn.spring.advice.SayServiceImpls], but was actually of type [$Proxy4] <property name="proxyInterfaces"> <array> <value>www.csdn.spring.proxy.advice.SayService</value> </array> </property> <property name="proxyTargetClass"> <value>true</value> </property> --> <!-- 目标对象 --> <property name="target"> <ref bean="sayServiceImpls"/> </property> <!-- 织入的通知的名称 --> <property name="interceptorNames"> <array> <value>beforeAdvice</value> <value>afterAdvice</value> <value>aroundAdvice</value> <value>throwAdvice</value> </array> </property> </bean></beans>
真实主题:SayServiceImpls.java
package www.csdn.spring.proxy.advice;public class SayServiceImpls{public void say(String content) {System.out.println("say:"+content);}}测试类 AdviceTests.javapackage www.csdn.spring.proxy.advice;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class AdviceTests {@Testpublic void testAdvice() {ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-advices.xml");// 不使用代理的时候// context.getBean("sayServiceImpls",SayServiceImpls.class).say("嗨!你好!");// 使用代理的时候context.getBean("proxyFactoryBean", SayServiceImpls.class).say("嗨!你好!");}}
3.静态切入点
为什么会有静态切入点,上一篇看博客已经介绍过,为了使你编写的通知,即代理在指定切入点起作用,也就是所谓的是aop的通知有实用价值。这里通过案例详细分析静态切入点。
spring-staticAdvisor.xml spring配置文件
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 创建前置通知 --> <bean id="beforeAdvice" class="www.csdn.spring.proxy.advice.BeforeAdvice"/> <!-- 创建后置通知 --> <bean id="afterAdvice" class="www.csdn.spring.proxy.advice.AfterAdvice"/> <!-- 创建环绕通知 --> <bean id="aroundAdvice" class="www.csdn.spring.proxy.advice.AroundAdvice"/> <!-- 创建异常通知 --> <bean id="throwAdvice" class="www.csdn.spring.proxy.advice.ThrowAdvice"/> <!-- 静态切入点 --> <bean id="nameMatchMethodPointcutAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> <!-- 织入通知,比如环绕通知 --> <property name="advice"> <ref bean="aroundAdvice"/> </property> <!-- 指明切入点 --> <property name="mappedName"> <value>say</value> </property> </bean> <!-- 真实主题 目标对象 --> <bean id="sayServiceImpl" class="www.csdn.spring.proxy.advice.SayServiceImpl"/> <!-- 配置代理操作 --> <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"> <!--抽象主题 实现接口 --> <property name="proxyInterfaces"> <array> <value>www.csdn.spring.proxy.advice.SayService</value> </array> </property> <!-- 目标对象 --> <property name="target"> <ref bean="sayServiceImpl"/> </property> <!-- 织入的通知的名称 --> <property name="interceptorNames"> <array> <value>nameMatchMethodPointcutAdvisor</value> </array> </property> </bean></beans>
测试类 AdvisorTest.javapackage www.csdn.spring.proxy.advice;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class AdvisorTest {@Testpublic void testAdvice() {ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-s*.xml");// 使用代理的时候SayService sayService = context.getBean("proxyFactoryBean", SayService.class);sayService.say("嗨!杨凯,你好!");sayService.sayHi();sayService.sayHello();sayService.byebye();}}
4.正则切入点
闲话少说,与静态切入点不同的就是正则切入点匹配正则表达式,重点代码见下面红色部分.
spring-regAdvisor.xml spring配置文件
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 创建环绕通知 --> <bean id="aroundAdvice" class="www.csdn.spring.proxy.advice.AroundAdvice"/> <!-- 静态切入点 --> <bean id="regexpMethodPointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <!-- 织入通知,比如环绕通知 --> <property name="advice"> <ref bean="aroundAdvice"/> </property> <!-- 指明切入点 --> <property name="patterns"> <!-- .是通配符的意思;第一个.*代表匹配任何包名和类名 ;第二个.*代表匹配以say开头的任意方法--> <array> <value>.*sayH.</value> <value>.*bye.*</value> <value>www.*\.SayService\.sayHell.</value> </array> </property> </bean> <!-- 真实主题 目标对象 --> <bean id="sayServiceImpl" class="www.csdn.spring.proxy.advice.SayServiceImpl"/> <!-- 配置代理操作 --> <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"> <!--抽象主题 实现接口 --> <property name="proxyInterfaces"> <array> <value>www.csdn.spring.proxy.advice.SayService</value> </array> </property> <!-- 目标对象 --> <property name="target"> <ref bean="sayServiceImpl"/> </property> <!-- 织入的通知的名称 --> <property name="interceptorNames"> <array> <value>regexpMethodPointcutAdvisor</value> </array> </property> </bean></beans>
测试类 AdvisorTest.java
package www.csdn.spring.proxy.advice;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class AdvisorTest {@Testpublic void testAdvice() {ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-r*.xml");// 使用代理的时候SayService sayService = context.getBean("proxyFactoryBean", SayService.class);sayService.say("嗨!杨凯,你好!");sayService.sayHi();sayService.sayHello();sayService.byebye();}}
- spring心得8--AOP各种通知案例讲解.doc
- Spring AOP 各种通知
- spring(AOP) 各种通知概念
- Spring AOP各种通知 以及执行顺序
- Spring AOP 通过XML方式配置各种通知
- oracle心得2--单行函数理论讲解与案例分析.doc
- spring心得6--自动装配知识点讲解及案例分析
- spring心得9--自动代理知识点讲解及案例分析
- Spring AOP-通知-前置通知
- Spring AOP-通知-后置通知
- Spring-AOP-通知-环绕通知
- Spring-AOP-通知-异常通知
- Spring-AOP通知
- spring AOP和通知
- Spring AOP-前置通知
- Spring AOP-后置通知
- Spring AOP 通知
- Spring AOP 四大通知
- spring心得7--spring第二大特点AOP(面向切面)讲解
- UPnP中Control Point的基本流程
- mergesort
- WCHAR和char的转换
- 中高级java软件工程师招聘要求
- spring心得8--AOP各种通知案例讲解.doc
- poj 1192 最优联通子集 简单dp
- Sql Server2000 转换成 MySQL 图文
- c语言位运算 求1个整数的二进制数有多少个1
- 高级项目管理师个人总结--项目计划
- poj 3613 Cow Relays (K步最短路+Floyd+矩阵快速幂)
- poj1042
- C#读写文件总结
- 青蛙跳河