Spring Note--AOP
来源:互联网 发布:js canvas 画图 编辑:程序博客网 时间:2024/04/19 12:52
Spring–AOP的概念
1 什么是AOP
- AOP:Aspect Oriented Programming的缩写,意思是面向切面编程,通过预编译方式运行期动态代理实现程序功能统一维护的一种技术
- 主要功能是:日志记录,性能统计,安全控制,事务处理,异常处理等
2 AOP实现方式
- 预编译:
- AspectJ
- 运行期间动态代理(JDK动态代理,CGLib动态代理)
- SpringAOP,JbossAOP
3 AOP相关关键词
4 Advice的类型
5 Spring框架中AOP用途
- 提供了声明式的企业服务,特别是EBJ的替代服务的声明
- EBJ解释:EJB (Enterprise JavaBean)是J2EE的一部分,定义了一个用于开发基于组件的企业多重应用程序的标准。其特点包括网络服务支持和核心开发工具(SDK)
- 允许用户定制自己的方面,已完成OOP和AOP的互补作用
6 Spring的AOP实现
- 纯Java 的实现,无需特殊的编译过程,不需要控制类的加载层次
- 目前只支持方法执行连接点(通知Spring Bean的方法执行)
- 不是提供了最完整的AOP实现;而是侧重于提供一种AOP实现和Spring Ioc容器之间的整合,用于帮助解决企业应用中的常见问题
- Spring AOP不会与AspectJ竞争,从而提供综合全面的AOP解决方案
7 有接口和无接口的Spring AOP实现区别
- Spring AOP默认使用标准的JavaSE动态代理作为AOP代理,这使得任何接口(或者接口集)都可以被代理
- Spring AOP中也可以使用CGLIB代理(如果一个业务对象并没有实现一个接口)
8 Advisors简介
- advisor就像一个小的自包含的面,只有一个advice
- 切面自身就是一个bean表示,并且必须实现某个advice接口,同时,advisor也可以很好的利用AspectJ的切入点表达式
- Spring通过配置文件中元素支持advisor实际使用中,大多数情况下它会和transactional advice配合使用
- 为了定义一个advisor的优先级以便让advice可以有序,使用order属性来定义advisor的顺序
9 AOP详解参考博文:
———-==博客参考链接(1)==———–
———-==博客参考链接(2)==——
10 SpringAOP配置的四种方式:
说了这么多,进入正题,如何配置Spring的AOP才是重点:
1. 经典的基于代理的AOP
2. @AspectJ注解驱动的切面
3. 纯POJO切面
4. 注入式AspectJ切面
10.1 经典的基于代理的AOP
介绍
- Spring1.2的历史用法现在的最新版本的框架依然支持
- SpringAOP的基础
- 现在的用法也是基于历史的,只不过更加方便了
实例
用到的接口和类
接口:
package com.bart.aopfour;public interface BizLogic { public String say();}
接口实现类:
package com.bart.aopfour;public class BizLogicImpl implements BizLogic{ @Override public String say() { System.out.println("BizLogicImpl:say()..."); return "BizLogicImpl`s say"; }}
切面类:
package com.bart.aopfour;import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;public class LogBefore implements MethodBeforeAdvice { public LogBefore(){} @Override public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable { System.out.println("LogBefore:"+arg0.getName()+" "+ arg2.getClass()); }}=======================分割线===========================package com.bart.aopfour;import java.lang.reflect.Method;import org.springframework.aop.AfterReturningAdvice;public class LogAfter implements AfterReturningAdvice { public LogAfter(){} @Override public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable { System.out.println("LogAfter:"+arg0.getClass()+" "+ arg1.getName()+arg3.getClass().getName()); }}
aopfour.xml文件的配置:
==此处注意:==
xml文件中根节点<beans ... />
的属性值必须完整跟示例的XML一样,否则会无法匹配相关的bean
<?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: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"> <!-- 使用Spring API 配置切面 --> <bean id="bizLogicImpl" class="com.bart.aopfour.BizLogicImpl"/> <bean id="logBefore" class="com.bart.aopfour.LogBefore" /> <bean id="logAfter" class="com.bart.aopfour.LogAfter" /> <!-- 配置切点有两种实现类 1. org.springframework.aop.support.JdkRegexpMethodPointcut 2. org.springframework.aop.support.NameMatchMethodPointcut --> <bean id="logPointcut" class="org.springframework.aop.support.NameMatchMethodPointcut"> <property name="mappedNames" > <list> <value>say*</value> </list> </property> </bean> <!-- 配置通知 --> <bean id="logAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="advice" ref="logBefore"/> <property name="pointcut" ref="logPointcut"/> </bean> <!-- 配置代理 --> <bean id="logProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="bizLogicImpl"/> <property name="proxyInterfaces" value="com.bart.aopfour.BizLogic"/> <property name="interceptorNames" > <list> <value>logAdvisor</value> <value>logAfter</value> </list> </property> </bean></beans>
测试:
context = new ClassPathXmlApplicationContext("aopfour.xml"); BizLogic bizLogic = (BizLogic) context.getBean("logProxy"); bizLogic.say();
输出结果:
LogBefore:say--class com.bart.aopfour.BizLogicImplBizLogicImpl:say()...LogAfter:class java.lang.String--say--com.bart.aopfour.BizLogicImpl
==注意事项==
在使用Spring API配置切面的Bean标签的时候注意一些id的单词是Spring框架固定的,不能改变,否则会报各种错误
1. 在配置pointcut的的时候如果要配置多个切点的list则注意此处
<bean id="logPointcut" class="org.springframework.aop.support.NameMatchMethodPointcut"> <property name="mappedNames" > <list> <value>say*</value> </list> </property> </bean>
<property />
标签的name值必须是”mappedNames”
2. 配置通知 的时候
<!-- 配置通知 --> <bean id="logAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="advice" ref="logBefore"/> <property name="pointcut" ref="logPointcut"/> </bean>
<property />
标签的name值必须是”advice”还有另外一个<property />
的name值必须是pointcut
3. 配置proxyBean代理的时候
<!-- 配置代理 --> <bean id="logProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="bizLogicImpl"/> <property name="proxyInterfaces" value="com.bart.aopfour.BizLogic"/> <property name="interceptorNames" > <list> <value>logAdvisor</value> <value>logAfter</value> </list> </property> </bean>
<property />
标签的name值依次固定格式为:target,proxyInterfaces,interceptorNames
==以上注意事项,千万谨记。否则会报出各种的错误==
10.2 @AspectJ注解驱动的切面
AspectJ的特点
- @AspectJ的风格类似纯java注解的普通java类
- Spring可以使用AspectJ来坐切入点解析
- AOP的运行时仍旧是纯的Spring AOP,对AspectJ的编译器或者组织无依赖性
AspectJ的来两种配置方式
- 对@AspectJ支持可以使用XML或者Java风格的配置
- 确保AspectJ的aspectjweaver.jar库包含在应用程序(jdk1.68或者更高)的classpath中
注解中用到的一些属性
@Configuration@EnableAspectJAutoProxypublic class AppConfig {}
<aop:aspectj-autoproxy />
实例:
用到的接口和类
接口:
package com.bart.aopfive;public interface BizLogicalInterface { public String say(String arg); public String talk();}
实现类和切面:
import org.springframework.stereotype.Service;@Servicepublic class BizLogicalImpl implements BizLogicalInterface { @Override public String say(String arg) { System.out.println("BizLogicalImpl:say()--"+arg);// throw new RuntimeException("抛出异常"); return "say is successed"; } @Override public String talk() { System.out.println("BizLogicalImpl:talk()..."); return null; }}=========================分割线==================================package com.bart.aopfive;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;import org.springframework.stereotype.Component;@Component@Aspectpublic class BartAspect { //配置切点 注意此处的execution后面的*say(..)括号里要加上两个点,否则无法匹配参数 @Pointcut("execution(* com.bart.aopfive.BizLogicalImpl.*say(..))") public void pointcut(){} @Pointcut("execution(* com.bart.aopfive.BizLogicalImpl.*talk())") public void bizPointcut(){} //配置前置通知 @Before("pointcut()") public void before() { System.out.println("BartAspect:before()..."); } //前置通知带参数 @Before("pointcut() && args(arg)") public void beforeWithParam(String arg) { System.out.println("BartAspect:beforeWithArgs--"+arg); } //配置后只通知 @After("pointcut()") public void after() { System.out.println("BartAspect:after()..."); } //配置后置返回通知 @AfterReturning(pointcut="pointcut()",returning="returnValue") public void afterReturning(Object returnValue) { System.out.println("BartAspect:afterReturning--"+returnValue); } //配置around通知 @Around("pointcut()") public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("BartAspect:around--1"); Object obj = pjp.proceed(); System.out.println("BartAspect:around--1"); System.out.println("BartAspect:around--"+obj); return obj; } //配置抛出异常通知 @AfterThrowing(pointcut="pointcut()",throwing="ex") public void afterThrowing(RuntimeException ex) { System.out.println("BartAspect:afterThrowing:"+ex.getMessage()); }}
配置aopfive.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: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"> <!-- 使用 AspectJ 注解 配置切面 --> <context:component-scan base-package="com.bart.aopfive"/> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
测试:
context = new ClassPathXmlApplicationContext("aopfive.xml");//此处必须视线接口才不会报错,否则要在aopfive.xml文件中配置proxyTargetClass属性为true,//意思是强制使用CGLIB代理BizLogicalInterface bli = (BizLogicalInterface) context.getBean("bizLogicalImpl"); bli.say("test param arg");//bli.talk();
测试结果:
BartAspect:around--1BartAspect:before()...BartAspect:beforeWithArgs--test param argBizLogicalImpl:say()--test param argBartAspect:around--1BartAspect:around--say is successedBartAspect:after()...BartAspect:afterReturning--say is successed
10.3 纯POJO切面
每个关注点集中于一处,而不是分散到多处代码中
服务模块更加简洁,因为它们只包含主要关注点的代码,次要关注点被转移到切面中了
Introduction简介:
允许一个==切面==(AspectImpl)声明一个==指定接口==(AdviceInterface)的通知对象
并且提供一个==接口的实现类==(AdviceImpl)来代表这些对象
本质意义是在不改变==目标类==(BartExp)的源码的前提下,增添新的方法
相当于给目标类实现了一个接口,但又不必更改目标类的源码
通过xml文件是配置来实现aop
实例:
用到的接口和类
目标类:
/* * 被切面作用的对象 * */package com.bart.aopthree;public class BartExp { public void bartSay() { System.out.println("BartExp: bartSay() method"); //测试afterThrowing //throw new RuntimeException("say failured..."); } public void bartInit(String name,int times) { System.out.println("BartExp: bartInit():"+name+" "+times); }}
切面接口及其实现类:
package com.bart.aopthree;public interface AspectInterface { public void say();}===============分割线======================/* * 切面对象 * */package com.bart.aopthree;import org.aspectj.lang.ProceedingJoinPoint;public class AspectImpl implements AspectInterface{ public void say() { System.out.println("AspectImpl:say() method"); } public void before() { System.out.println("AspectImpl: before"); } public void afterReturning() { System.out.println("AspectImpl: afterReturning"); } public void afterThrowing() { System.out.println("AspectImpl: afterThrowing"); } public void after() { System.out.println("AspectImpl: after"); } public Object around(ProceedingJoinPoint pjp) { Object obj = null; try { System.out.println("AspectImpl:around---1"); obj = pjp.proceed(); System.out.println("AspectImpl:around---2"); System.out.println("AspectImpl:around---"+obj); } catch (Throwable e) { e.printStackTrace(); } return obj; } public Object aroundInit(ProceedingJoinPoint pjp,String name,int times) { System.out.println("AspectImpl:aroundInit:"+name+" "+times); Object obj = null; try { System.out.println("AspectImpl:around---1"); obj = pjp.proceed(); System.out.println("AspectImpl:around---2"); System.out.println("AspectImpl:around---"+obj); } catch (Throwable e) { e.printStackTrace(); } return obj; }}
Introduction(简介)接口及其实现类:
package com.bart.aopthree;public interface AdviceInterface { public void say(); public void eat();}================分割线================package com.bart.aopthree;public class AdviceImpl implements AdviceInterface { public void say() { System.out.println("AdviceImpl:say()"); } public void eat() { System.out.println("AdviceImpl:eat()"); }}
aopthree.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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <bean id="aspectImpl" class="com.bart.aopthree.AspectImpl"/> <bean id="bartExp" class="com.bart.aopthree.BartExp"/> <aop:config> <aop:aspect id="aspectImplAOP" ref="aspectImpl"> <aop:pointcut expression="execution(* com.bart.aopthree.BartExp.bartSay())" id="aspectImplPointcut"/> <aop:before method="before" pointcut-ref="aspectImplPointcut"/> <aop:after-returning method="afterReturning" pointcut-ref="aspectImplPointcut"/> <aop:after-throwing method="afterThrowing" pointcut-ref="aspectImplPointcut"/> <aop:after method="after" pointcut-ref="aspectImplPointcut"/> <aop:around method="around" pointcut-ref="aspectImplPointcut"/> <!-- 带参数的环绕 --> <aop:around method="aroundInit" pointcut="execution(* com.bart.aopthree.BartExp.bartInit(String,int)) and args(name,times)"/> <!-- introductions(简介) --> <aop:declare-parents types-matching="com.bart.aopthree.BartExp" implement-interface="com.bart.aopthree.AdviceInterface" default-impl="com.bart.aopthree.AdviceImpl"/> </aop:aspect> </aop:config> </beans>
测试1:
context=new ClassPathXmlApplicationContext("aopthree.xml"); BartExp bartExp = (BartExp) context.getBean("bartExp"); bartExp.bartSay();
测试1输出结果:
AspectImpl: beforeAspectImpl:around---1BartExp: bartSay() methodAspectImpl:around---2AspectImpl:around---nullAspectImpl: afterAspectImpl: afterReturning
测试2:
context=new ClassPathXmlApplicationContext("aopthree.xml");BartExp bartExp = (BartExp) context.getBean("bartExp");bartExp.bartInit("Bart", 3);
测试2输出结果:
AspectImpl:aroundInit:Bart 3AspectImpl:aroundInit---1BartExp: bartInit():Bart 3AspectImpl:aroundInit---2AspectImpl:aroundInit---null
测试3(Introduction):
context=new ClassPathXmlApplicationContext("aopthree.xml");BartExp bartExp = (BartExp) context.getBean("bartExp"); /* introduction(简介)的使用测试 * 在不更改目标类(BartExp)的前提下增加新的方法 */AdviceInterface adviceInterface =(AdviceInterface)context.getBean("bartExp");//添加的方法adviceInterface.say();adviceInterface.eat();//bart原来的方法BartExp bartExp = (BartExp)adviceInterface;bartExp.bartSay();
测试3输出结果:
AdviceImpl:say()AdviceImpl:eat()AspectImpl: beforeAspectImpl:around---1BartExp: bartSay() methodAspectImpl:around---2AspectImpl:around---nullAspectImpl: afterAspectImpl: afterReturning
10.4 注入式AspectJ切面
该方法类似于纯POJO切面,只不过POJO在运行期编译,而AspectJ在运行前编译
详细了解==参考博文==
在初学的过程中遇到过很多不懂的地方自己也是查阅资料和阅读各位大神们的博客才搞明白的。也这篇博客记录了学习Spring的一些基础的知识。大部分是简单的小例子。便于初学者理解。博客的代码都是经过本人测试正确运行的。由于本人才学疏浅,难免会有不足或者遗漏的地方,还望读者见谅。
- Spring Note--AOP
- Spring v3.0.2 Learning Note 13 - AOP Example
- NOTE:Spring
- Spring note
- Spring note
- AOP、Spring的AOP
- AOP--Spring AOP
- Spring AOP 嵌套AOP
- spring AOP
- Spring AOP
- Spring AOP
- spring aop
- Spring AOP
- spring AOP
- spring aop
- Spring aop
- Spring-AOP
- Spring AOP
- Spring Note--IOC
- 漫谈OI中的群论入门
- 【集合框架】2. List容器
- 后序遍历 非递归方法 (利用辅助节点r)
- Java的IO之字符流(Reader)
- Spring Note--AOP
- Linux基础教程——LVM逻辑卷基本操作流程(附图)
- pip安装时ReadTimeoutError解决办法
- 程序猿(媛)实用颜色表 [颜色图示,英文代码,形象颜色,HEX格式,RGB格式]
- H
- 二叉树查找x的祖先
- 【HDU1398】Square Coins 母函数
- 案例2_健康栏目的实现分析
- 【Linux基础】Linux/Windows下安装python、Numpy、Matplotlib