- 浏览: 55775 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
p_3er:
blucedong 写道你好我在做struts1.3+spri ...
基于annotation的struts1.3+hibernate3.3+spring2.5 -
blucedong:
你好我在做struts1.3+spring3.0+hibern ...
基于annotation的struts1.3+hibernate3.3+spring2.5
第三章 AOP 通过Java API创建切面
在前面使用增强的时候,我们发现增强会被织入到目标类的所有的方法中。我们如果把增强织入到目标类的特定的方法中,需要使用切点进行目标连接点的定位。然后我们可以通过切点及增强生成一个切面了。
3.4.1切点类型
静态方法切点:org.springframework.aop.support.StaticMethodMatcherPointcut
动态方法切点:org.springframework.aop.support.DynamicMethodMatcherPointcut
注解切点:org.springframework.aop.support.annotation.AnnotationMatchingPointcut
表达式切点:org.springframework.aop.support.ExpressionPointcut
流程切点:org.springframework.aop.support.ControlFlowPointcut
3.4.2静态方法来匹配切面
org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor
a、增强类
在这里使用的是3.3.2的前置增强:
http://blog.csdn.net/p_3er/article/details/9239925
只是UserDaoImpl中有两个方法,save方法和delete方法。然后我们给save方法配置切面。
b、切面类继承StaticMethodMatcherPointcutAdvisor
public class StaticAdvisor extends StaticMethodMatcherPointcutAdvisor { /* * 切点方法匹配规则 */ public boolean matches(Method method, Class<?> clazz) { return method.getName().equals("save"); } /* * 重写StaticMethodMatcherPointcut的getClassFilter() * 匹配哪个类下的方法 */ public ClassFilter getClassFilter() { ClassFilter classFilter = new ClassFilter() { public boolean matches(Class<?> clazz) { return UserDaoImpl.class.isAssignableFrom(clazz); } }; return classFilter; } }
c、配置
<!-- 增强Bean --> <bean id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean> <!-- 目标Bean --> <bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean> <!-- 管理切面类。p:advice-ref把增强放入切面 --> <bean id="staticAdvisor" class="cn.framelife.spring.advisor.StaticAdvisor" p:advice-ref="userDaoBeforeAdvice"></bean> <!-- 设置父代理类 p:interceptorNames 放切面,而不再是增强 --> <bean id="paramProxy" class="org.springframework.aop.framework.ProxyFactoryBean" p:interceptorNames="staticAdvisor" p:proxyTargetClass="true" /> <!-- 设置子代理类 --> <bean id="userDaoProxy" parent="paramProxy" p:target-ref="userDao"></bean>
d、测试
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"}); UserDao userDao = (UserDao) context.getBean("userDaoProxy"); //UserDaoImpl中有两个方法,save方法中有切面,delete中没切面 userDao.save(); System.out.println("----------"); userDao.delete();
e、结果
我是前置增强:save 保存用户... ---------- 删除用户...
3.4.3静态正则表达式方法配置切面
这种方法不需要自己写切面类。
org.springframework.aop.support.RegexpMethodPointcutAdvisor是正则表达式方法匹配的切面实现类。
a、增强类
在这里使用的是3.3.2的前置增强:
http://blog.csdn.net/p_3er/article/details/9239925
b、配置
<!-- 增强Bean --> <bean id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean> <!-- 目标Bean --> <bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean> <!-- 设置切面Bean patterns 用正则表达式定义目标类全限定方法名的匹配模式串 目标类全限定方法名,指的是带类名的方法名。如: cn.framelife.spring.dao.impl.UserDaoImpl.delete() <value>.*delete</value> 匹配模式串 --> <bean id="regexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" p:advice-ref="userDaoBeforeAdvice"> <property name="patterns"> <list> <value>.*delete</value> </list> </property> </bean> <!-- 设置代理类 --> <bean id="regexpProxy" class="org.springframework.aop.framework.ProxyFactoryBean" p:interceptorNames="regexpAdvisor" p:target-ref="userDao" p:proxyTargetClass="true" />
c、测试
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"}); UserDao userDao = (UserDao) context.getBean("regexpProxy"); userDao.save(); System.out.println("----------"); userDao.delete();
d、结果
保存用户... ---------- 我是前置增强:delete 删除用户...
常用的正则表达式规则
1、.*set.*表示所有类中的以set为前缀的方法。如:com.abc.UserDao.setName()。
2、com\.abc\.service\..*表示com.abc.service.包下所有的类的所有的方法。
Com.abc.service.a.User.setName()
Com.abc.service.UserService.save()
3、com\.abc\.service\..*Service\..*表示com.abc.service包下以Service结尾的类的所有的方法。如:com.abc.service.UserService.save()
4、com\.abc\.service\..*Service\.save.+匹配所有以save为前缀的方法,而且save后必须拥有一个或多个字符。如:com.abc.service.UserService.saveUser()
3.4.4动态切面
org.springframework.aop.support.DynamicMethodMatcherPointcut类即有静态切点检查的方法,也有动态切点检查的方法。由于动态切点检查会对性能造成很大的影响,我们应当避免在运行时每次都对目标类的各个方法进行检查。
Spring检查动态切点的机制:在创建代理时对目标类的每个连接点进行静态切点检查,如果仅静态切点检查就可以知道连接点是不匹配的,在运行期就不进行动态检查了;如果静态切点检查是匹配的,在运行期才进行动态方法检查。
动态切面通过DefaultPointcutAdvisor切面类与DynamicMethodMatcherPointcut切点结合起来生成。主要是针对连接点方法的参数。
a、增强类
在这里使用的是3.3.2的前置增强:
http://blog.csdn.net/p_3er/article/details/9239925
只是UserDaoImpl中多了一个out方法,带一个参数。
b、切点类继承DynamicMethodMatcherPointcut
public class DynamicPointcut extends DynamicMethodMatcherPointcut { //用list集合保存参数名 private List<String> specialNames = new ArrayList<String>(); public DynamicPointcut(){ specialNames.add("aa"); specialNames.add("bb"); } /* * 对类进行静态切点检查 */ public ClassFilter getClassFilter() { return new ClassFilter() { @Override public boolean matches(Class<?> targetClass) { System.out.println("使用getClassFilter静态检查:"+targetClass.getName()); return UserDaoImpl.class.isAssignableFrom(targetClass); } }; } /* *对方法进行静态切点检查 */ public boolean matches(Method method, Class<?> targetClass) { System.out.println("使用matches(method,targetClass)方法静态检查:"+targetClass.getName()+"--"+method.getName()); return method.getName().equals("out"); } /* *对方法进行动态切点检查 */ public boolean matches(Method method, Class<?> targetClass, Object[] args) { System.out.println("使用matches(method,targetClass)方法动态检查:"+targetClass.getName()+"--"+method.getName()+"的参数"); String name = (String)args[0]; return specialNames.contains(name); } }
c、配置
<!-- 增强Bean --> <bean id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean> <!-- 目标Bean --> <bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean> <!-- 切面 --> <bean id="dynamicAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <!-- 设置切点 --> <property name="pointcut"> <bean class="cn.framelife.spring.pointcut.DynamicPointcut"></bean> </property> <!-- 织入增强 --> <property name="advice" ref="userDaoBeforeAdvice"></property> </bean> <!-- 设置代理 --> <bean id="dynamicProxy" class="org.springframework.aop.framework.ProxyFactoryBean" p:interceptorNames="dynamicAdvisor" p:target-ref="userDao" p:proxyTargetClass="true" />
d、测试
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"}); UserDao userDao = (UserDao) context.getBean("dynamicProxy"); //UserDaoImpl中多了一个out方法,带一个参数。 System.out.println("----------"); userDao.save(); System.out.println("----------"); userDao.out("aa"); System.out.println("----------"); userDao.out("1111"); System.out.println("----------");
e、结果
使用getClassFilter静态检查:cn.framelife.spring.dao.impl.UserDaoImpl 使用matches(method,targetClass)方法静态检查:cn.framelife.spring.dao.impl.UserDaoImpl--out 使用getClassFilter静态检查:cn.framelife.spring.dao.impl.UserDaoImpl 使用matches(method,targetClass)方法静态检查:cn.framelife.spring.dao.impl.UserDaoImpl--save 使用getClassFilter静态检查:cn.framelife.spring.dao.impl.UserDaoImpl 使用matches(method,targetClass)方法静态检查:cn.framelife.spring.dao.impl.UserDaoImpl--delete 使用getClassFilter静态检查:cn.framelife.spring.dao.impl.UserDaoImpl 使用matches(method,targetClass)方法静态检查:cn.framelife.spring.dao.impl.UserDaoImpl--clone 使用getClassFilter静态检查:cn.framelife.spring.dao.impl.UserDaoImpl 使用matches(method,targetClass)方法静态检查:cn.framelife.spring.dao.impl.UserDaoImpl--toString ---------- 使用getClassFilter静态检查:cn.framelife.spring.dao.impl.UserDaoImpl 使用matches(method,targetClass)方法静态检查:cn.framelife.spring.dao.impl.UserDaoImpl--save 保存用户... ---------- 使用getClassFilter静态检查:cn.framelife.spring.dao.impl.UserDaoImpl 使用matches(method,targetClass)方法静态检查:cn.framelife.spring.dao.impl.UserDaoImpl--out 使用matches(method,targetClass)方法动态检查:cn.framelife.spring.dao.impl.UserDaoImpl--out的参数 我是前置增强:out out输出名字为:aa ---------- 使用matches(method,targetClass)方法动态检查:cn.framelife.spring.dao.impl.UserDaoImpl--out的参数 out输出名字为:1111 ----------
3.4.5流程切面
一个类中的某一方法使用目标类的两个方法,那么我们可以使用流程切面给这两个方法都积入增强。
如:UserServiceImpl类(使用类)operate方法中使用UserDaoImpl(目标类)的两个方法。
流程切面使用ControlFlowPointcut与DefaultPointcutAdvisor结合形成。
a、增强类
在这里使用的是3.3.2的前置增强:
http://blog.csdn.net/p_3er/article/details/9239925
只是UserDaoImpl中有两个方法,save方法和delete方法。然后我们给save方法配置切面。
b、UserServiceImpl类
public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void addUser() { userDao.save(); } @Override public void operate() { //这里同时使用了userDao的两个方法 userDao.delete(); userDao.save(); } }
c、配置
<!-- 增强Bean --> <bean id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean> <!-- 目标Bean --> <bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean> <!-- 切点 --> <bean id="controlFlowPointcut" class="org.springframework.aop.support.ControlFlowPointcut"> <!-- 指定流程切点的类 --> <constructor-arg type="java.lang.Class" value="cn.framelife.spring.service.impl.UserServiceImpl"></constructor-arg> <!-- 指定流程切点的方法 --> <constructor-arg type="java.lang.String" value="operate"></constructor-arg> </bean> <!-- 切面 --> <bean id="controlFlowAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor" p:pointcut-ref="controlFlowPointcut" p:advice-ref="userDaoBeforeAdvice"/> <!-- 设置代理 --> <bean id="controlFlowProxy" class="org.springframework.aop.framework.ProxyFactoryBean" p:interceptorNames="controlFlowAdvisor" p:target-ref="userDao" p:proxyTargetClass="true" /> <!-- 把使用目标类的Bean交由Spring管理 --> <bean id="userService" class="cn.framelife.spring.service.impl.UserServiceImpl"> <property name="userDao" ref="controlFlowProxy"></property> </bean>
d、测试
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"}); UserService userService = (UserService) context.getBean("userService"); userService.operate(); System.out.println("----------------"); userService.addUser();
e、结果
我是前置增强:delete 删除用户... 我是前置增强:save 保存用户... ---------------- 保存用户...
3.4.6复合切面
在前面的例子中,我们所定义的切面都只有一个切点而已。有时候我们一个切面需要多个切点,也就是多个条件才能决定连接点。多个切点组成一个切点,这样的切点是复合切点。由复合切点加上增强形成的切面,称为复合切面。
a、增强类
在这里使用的是3.3.2的前置增强:
http://blog.csdn.net/p_3er/article/details/9239925
b、一个普通类中有一个获取Pointcut的方法
public class MyPointcut { //获取Pointcut的方法名是get开头 public Pointcut getMyComposablePointcut(){ //创建一个复合切点 ComposablePointcut cp = new ComposablePointcut(); //创建一个流程切点(参数:使用类、类中的方法)这里使用的是3.4.5中的UserServiceImpl类 Pointcut pt1 = new ControlFlowPointcut(UserServiceImpl.class,"operate"); //创建一个静态方法切点 Pointcut pt2 = new StaticMethodMatcherPointcut() { public boolean matches(Method method, Class<?> clazz) { return UserDaoImpl.class.isAssignableFrom(clazz)&&method.getName().equals("delete"); } }; //两个切点进行交集操作. return cp.intersection(pt1).intersection(pt2); } }
c、配置
<!-- 增强Bean --> <bean id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean> <!-- 目标Bean --> <bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean> <!-- 切点所在类 --> <bean id="myPoincut" class="cn.framelife.spring.pointcut.MyPointcut"></bean> <!-- 切面 p:pointcut #{ myPoincut.myComposablePointcut} 是由MyPointcut的getMyComposablePointcut方法获取的 --> <bean id="composableAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor" p:pointcut="#{ myPoincut.myComposablePointcut}" p:advice-ref="userDaoBeforeAdvice"/> <!-- 设置代理 --> <bean id="composableProxy" class="org.springframework.aop.framework.ProxyFactoryBean" p:interceptorNames="composableAdvisor" p:target-ref="userDao" p:proxyTargetClass="true" /> <!-- 把使用目标类的Bean交由Spring管理 --> <bean id="userService" class="cn.framelife.spring.service.impl.UserServiceImpl"> <property name="userDao" ref="composableProxy"></property> </bean>
d、测试
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"}); UserService userService = (UserService) context.getBean("userService"); userService.operate();
e、结果
我是前置增强:delete 删除用户... 保存用户...
3.4.7引介切面
a、使用3.3.6引介增强里面的东西(接口与增强类)
b、配置
<!-- 目标Bean --> <bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean> <!-- 切面 constructor-arg 设置引介增强 --> <bean id="introductionAdvisor" class="org.springframework.aop.support.DefaultIntroductionAdvisor"> <constructor-arg> <bean class="cn.framelife.spring.advice.IntroductionAdvice"></bean> </constructor-arg> </bean> <!-- 设置代理 --> <bean id="incluctionProxy" class="org.springframework.aop.framework.ProxyFactoryBean" p:interceptorNames="introductionAdvisor" p:target-ref="userDao" p:proxyTargetClass="true" />
c、测试
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"}); UserDao userDao = (UserDao) context.getBean("aProxy"); userDao.save(); System.out.println("-------------"); AInterface a = (AInterface)userDao; a.say(); System.out.println("-------------"); userDao.save();
d、结果
方法执行前执行 org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation save 保存用户... 方法执行后执行 ------------- 方法执行前执行 org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation say UserDao要说话 方法执行后执行 ------------- 方法执行前执行 org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation save 保存用户... 方法执行后执行
相关推荐
Spring AOP API 设计与实现是Spring框架的重要组成部分,它提供了面向切面编程的能力,使得开发者可以在不修改源代码的情况下,对程序进行横切关注点的处理,如日志记录、事务管理等。本章主要涵盖了Spring AOP的多...
Spring AOP,全称为Spring面向切面编程,是Java EE企业级应用开发中的一个重要组成部分。它提供了一种在不改变原有代码的情况下,通过添加额外功能(如日志、事务管理)来增强程序的能力。AOP的主要目标是解决传统...
在Java中,通常使用Servlet API或者第三方库如Apache Commons FileUpload来实现。Servlet 3.0及以上版本提供了内置的Part接口支持文件上传,而FileUpload库则提供更灵活的配置和错误处理机制。在处理文件上传时,...
面向切面编程(Aspect-Oriented Programming,AOP)是一种编程范式,旨在将关注点分离,使得系统中的交叉关注点,如日志、事务管理、权限检查等,可以从核心业务逻辑中解耦出来。在Java领域,Spring框架是AOP的典型...
在Java中,API包括了Java核心库(JDK)和许多第三方库。 1. **Java核心API**: - **IO流**:Java.IO包包含了处理输入输出操作的各种类,如InputStream、OutputStream、Reader、Writer等,用于读写文件、网络数据...
AOP联盟(aopalliance)是Java平台上的一个开源项目,提供了一个统一的API,使得不同的AOP框架可以共享相同的切面实现。aopalliance-1.0.jar是这个项目的标准库,包含了一系列基础接口,使得不同的AOP框架如Spring、...
2. **动态代理增强**:增强了Java反射机制,允许创建动态代理类,方便实现回调和AOP(面向切面编程)。 3. **Scripting API**:允许在Java应用程序中集成脚本语言,如JavaScript、Groovy等。 4. **XML改进**:包括...
在Java领域,Spring框架是AOP应用的典型代表,但在Android开发中,由于原生API并未直接支持AOP,我们需要借助第三方库来实现这一功能。 在Android中,AOP通常用于提升代码的可维护性和可扩展性。通过在不修改原有...
在Java中,Spring框架提供了强大的AOP支持,通过定义切面、通知类型(前置、后置、异常、环绕等)来实现切面的织入。描述中的例子展示了如何使用AOP进行日志处理,这能帮助开发者更好地跟踪和理解程序运行情况,同时...
在本章中,我们将深入探讨Spring MVC框架与Servlet API以及JSON支持的相关知识。...在实践中,不断探索和学习Spring MVC的高级特性,如AOP(面向切面编程)、拦截器、异常处理等,将有助于提升项目的整体质量。
这个API文档详细列出了Spring框架的核心组件,如依赖注入、AOP(面向切面编程)、数据访问/集成、Web支持等。通过学习,开发者可以掌握如何利用Spring来构建松散耦合、测试驱动和基于组件的应用程序。 4. Struts1.3...
7. **Spring框架**:Spring是Java EE开发中的核心框架,提供AOP(面向切面编程)、DI、事务管理等功能。如果涉及Spring,代码可能包含配置XML文件或基于Java的配置,以及使用`@Component`、`@Service`、`@Repository...
JFinal 提供了快速开发的功能,如自动化映射字段、拦截器、AOP(面向切面编程)支持等。在这个项目中,JFinal 被用来构建服务器端,处理来自 CoolQ HTTP API 的请求,并通过 SDK 进行相应的操作。 具体到这个名为 ...
3. **第三章:JSP** - JSP(JavaServer Pages)用于动态网页生成,讲解JSP语法、EL(Expression Language)和JSTL(JavaServer Pages Standard Tag Library)。 4. **第四章:MVC模式** - 介绍Model-View-...
7. **Spring框架基础**(17章):Spring是Java企业级应用的核心框架,提供依赖注入、AOP(面向切面编程)、数据访问等服务。虽然这部分未包含,但了解Spring对Java Web开发极其重要。 8. **Struts和Hibernate集成**...
Spring是Java Web开发中最受欢迎的框架之一,提供依赖注入、AOP(面向切面编程)等功能。本章将介绍Spring的基本概念和配置。 第十章:Spring MVC与RESTful API Spring MVC是Spring框架的一部分,用于构建Web应用。...
动态代理则可以创建在运行时生成的代理类,以提供额外的功能,如AOP(面向切面编程)。 5. **集合框架高级特性和并发容器**:可能包括`ConcurrentHashMap`、`CopyOnWriteArrayList`、`BlockingQueue`等并发容器的...
Java相关jar包是一个重要的软件开发资源集合,主要涵盖了Spring框架的4.0版本,DOM处理库dom4j,以及AOP(面向切面编程)相关的类库,还有用于查看Java源码的MyEclipse反编译工具。这些组件在Java开发中扮演着不可或...
7. **Spring框架**:Spring是轻量级Java EE开发的代表,提供了全面的解决方案,包括依赖注入、AOP(面向切面编程)、事务管理等,极大地简化了企业应用的开发。 8. **RESTful Web服务**:使用JAX-RS(Java API for ...
15. **第16章:Spring框架** - Spring是Java应用开发中的重要框架,涵盖了依赖注入、AOP(面向切面编程)、Spring Boot、Spring MVC等内容。 16. **第17章:MyBatis持久层框架** - MyBatis简化了数据库操作,结合...