Spring系列学习之Spring AOP
1.何谓AOP?
aop是开发中面向切面编程的一种思想
AOP与OOP的对比:OOP是面向对象编程的一种思想。即模拟现实世界模式一切皆对象;AOP是面前切面,即将过程横切处理的思想。
2.AOP的作用:
1.提供了声明式的服务
2.允许用户定义自己的切面
3.AOP常见的实现:
1.Proxy方式实现AOP方式:
2.CGLib方法实现AOP
3.Spring AOP实现:注解aspect方式实现;基于配置文件方式实现
4.Spring AOP的实现:
1.纯Java实现,无需特殊编译过程,不需要控制类加载层次;
2.只支持方法执行连接点
3.不是为了提供最完整的AOP实现,而是侧重提供一种AOP实现与Spring IOC容器之间的整合,用于帮助企业级应用提供常见问题的解决途径。
4.Spring AOP默认使用标准的JavaSE动态代理作为AOP的代理器,使得所用的接口都可以被代理
5.Spring AOP代理也可以使用CGLib代理
5.Spring AOP实现之基于注解aspect方式实现:
1.代理对象业务代码:
package aop.aspect; public class Student { public String print(String name) { System.out.println(name + "print"); return "hello word"; } }
2.注解实现的切面代码
package aop.aspect; 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.aspectj.lang.annotation.Pointcut; @Aspect public class StudnetInterceptor { /** * 打印方法AOP */ @Pointcut("execution(* aspect.Student.print(..))") // @Pointcut("execution(* // com.jike.spring.chapter09.aop.aspect.Student.*(..))") public void printMethod() { } @Before("printMethod()") public void printBeforeAdvice() { System.out.println("printBeforeAdvice()!"); } @AfterReturning(pointcut = "printMethod()", returning = "flag") public void printAfterAdvice(String flag) { System.out.println("printAfterAdvice()! " + flag); } @After("printMethod()") public void finallyAdvice() { System.out.println("finallyAdvice()!"); } @Around("printMethod() && args(name)") public Object printAroundAdvice(ProceedingJoinPoint pjp, String name) throws Throwable { Object result = null; if (name.equals("whc")) pjp.proceed(); else System.out.println("print()方法以及被拦截..."); return result; } }
3.测试代码:
public class Test { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("config/conf-aspect.xml"); Student stu = (Student) ctx.getBean("stu"); stu.print("whc"); } }
6.Spring AOP实现之aspect配置文件方式实现:
1.被代理对象的业务事务代码
package aop.xml; public class Student { public String print(String name) { System.out.println(name + "print"); return "hello word"; } }
2.基于配置文件实现的切面代码
package aop.xml; 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.aspectj.lang.annotation.Pointcut; /** * Xml方式实现AOP切面 * * @author lilin * @time 2016年5月27日 下午11:46:46 * @email gaosi0812@gmail.com * @blog http://gaosililin.iteye.com * @school USC * @team Geowind */ public class StudnetInterceptor { /** * 打印方法AOP */ public void printMethod() { } public void printBeforeAdvice() { System.out.println("printBeforeAdvice()!"); } public void printAfterAdvice(String name) { System.out.println("printAfterAdvice()! " + name); } public void finallyAdvice() { System.out.println("finallyAdvice()!"); } public Object printAroundAdvice(ProceedingJoinPoint pjp, String name) throws Throwable { Object result = null; if (name.equals("whc")) pjp.proceed(); else System.out.println("print()方法以及被拦截..."); return result; } }
3.测试代码:
package aop.xml; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("config/conf-xml.xml"); Student stu = (Student) ctx.getBean("stu"); stu.print("whc1"); } }
4.配置文件:
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"> <aop:aspectj-autoproxy /> <bean id="stu" class="xml.Student"></bean> <bean id="interceptor" class="xml.StudnetInterceptor"></bean> <aop:config> <aop:aspect id="stuInterceptor" ref="interceptor"> <aop:before pointcut="execution(* xml.Student.print(..))" method="printBeforeAdvice" /> <aop:after-returning pointcut="execution(* xml.Student.print(..))" method="printAfterAdvice" /> <aop:after pointcut="execution(* xml.Student.print(..))" method="finallyAdvice" /> <aop:around pointcut="execution(* .xml.Student.print(..)) and args(name)" method="printAroundAdvice" /> </aop:aspect> </aop:config> </beans>
7.Spring pointCut:
8.aop通知的执行的顺序:
1.before:方法执行前
2.around:环绕,方法执行之前,但是该方法第一个参数必须是ProceedingJoinPoint
3.after-throwing:方法抛出异常之后
4.after:方法执行之后
5.after-returning:方法返回值之后
示例代码:
1.目标接口代码
package aop.aop; public interface Foo { void play(String name); }
2.目标接口实现类代码
package aop.aop; public class FooImpl implements Foo { @Override public void play(String name) { System.out.println("paling with " + name); throw new RuntimeException(); } }
3.Interceptor类代码
package aop.aop; import org.aspectj.lang.ProceedingJoinPoint; /** * Xml配置实现通知 * * @author lilin * @time 2016年5月31日 下午12:36:52 * @email gaosi0812@gmail.com * @blog http://gaosililin.iteye.com * @school USC * @team Geowind */ public class FooInterceptor { /** * 前置通知 */ public void beforePaly() { System.out.println("FooInterceptor.beforePlay"); } /** * 后置通知 */ public void afterPlay() { System.out.println("FooInterceptor.afterPlay"); } /** * 返回返回值后通知 */ public void afterReturnning() { System.out.println("FooInterceptor.afterReturnning"); } /** * 抛出异常后通知 */ public void throwExcetion() { System.out.println("FooInterceptor.throwExcetion"); } /** * 环绕通知 。第一个参数必须是ProceedingJoinPoint * * @param pjp * @param name * @return * @throws Throwable */ public Object printAroundAdvice(ProceedingJoinPoint pjp, String name) throws Throwable { Object result = null; if (name.equals("jing")) { try { result = pjp.proceed(); } catch (Exception e) { System.out.println("诶呀,异常了"); } } else { System.out.println("print()方法以及被拦截..."); } return result; } }
4.测试类代码
package aop.aop; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AopTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("config/introduce-introduce.xml"); Foo foo = (Foo) context.getBean("foo"); foo.play("jing"); } }
5.配置文件
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"> <aop:aspectj-autoproxy /> <bean id="foo" class="aop.aop.FooImpl"></bean> <bean id="foointerceptor" class="aop.aop.FooInterceptor"></bean> <aop:config> <aop:aspect id="fooInterceptor" ref="foointerceptor"> <aop:before method="beforePaly" pointcut="execution(* aop.aop.Foo.play(..) )" /> <aop:after-returning method="afterReturnning" pointcut="execution(* aop.aop.Foo.play(..))" /> <aop:after method="afterPlay" pointcut="execution(* aop.aop.Foo.play(..))" /> <aop:around pointcut="execution(* aop.aop.Foo.play(..)) and args(name)" method="printAroundAdvice" /> <aop:after-throwing method="throwExcetion" pointcut="execution(* aop.aop.Foo.play(..))" /> </aop:aspect> </aop:config> </beans>
6.结果排序
9.Advice AOP增强
Aop Advice中除了Introdutions引介增强外,其他的都是方法级别的增强,Introdutions引介增强是类级别的增强
实现代码示例:
1.增强对象的接口
package advice.advice; /** * 增强对象的接口 * * @author lilin * @time 2016年5月31日 上午11:22:19 * @email gaosi0812@gmail.com * @blog http://gaosililin.iteye.com * @school USC * @team Geowind */ public interface Foo { void play(String name); }
2.增强的实现类
package advice.advice; /** * 增强对象的实现类 * * @author lilin * @time 2016年5月31日 上午11:22:45 * @email gaosi0812@gmail.com * @blog http://gaosililin.iteye.com * @school USC * @team Geowind */ public class FooImpl implements Foo { @Override public void play(String name) { System.out.println("paling with " + name); // throw new RuntimeException(); } }
3.前置增强
package advice.advice; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; /** * 前置增强 * * @author lilin * @time 2016年5月31日 上午11:27:42 * @email gaosi0812@gmail.com * @blog http://gaosililin.iteye.com * @school USC * @team Geowind */ public class BeforeAdvice implements MethodBeforeAdvice { @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("BeforeAdvice.before:method " + method.getName() + " aug:" + args[0]); } }
5.后置增强
package advice.advice; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; /** * 后置增强 * * @author lilin * @time 2016年5月31日 上午11:23:42 * @email gaosi0812@gmail.com * @blog http://gaosililin.iteye.com * @school USC * @team Geowind */ public class AfterAdvice implements AfterReturningAdvice { @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("AfterAdvice.afterReturning. method:" + method.getName() + " arg:" + args[0]); } }
6.环绕增强
package advice.advice; import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; /** * 环绕增强 * * @author lilin * @time 2016年5月31日 上午11:28:23 * @email gaosi0812@gmail.com * @blog http://gaosililin.iteye.com * @school USC * @team Geowind */ public class AroundAdvice implements MethodInterceptor { @Override public Object invoke(MethodInvocation arg0) throws Throwable { Method method = arg0.getMethod(); Object[] arguments = arg0.getArguments(); // 环绕增强 前 System.out.println("AroundAdvice.invoke.before method:" + method.getName()); // 放射方式调用目标方法 Object proceed = arg0.proceed(); // 环绕增强 后 System.out.println("AroundAdvice.invoke.after arg:" + arguments[0]); return proceed; } }
7.配置实现的配置文件
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- 前置增强 --> <bean id="beforeAdvice" class="advice.advice.BeforeAdvice"></bean> <!-- 后置增强 --> <bean id="afterAdvice" class="advice.advice.AfterAdvice"></bean> <!-- 环绕增强 --> <bean id="aroundAdvice" class="advice.advice.AroundAdvice"></bean> <!-- 增强的对象 --> <bean id="target" class="advice.advice.FooImpl"></bean> <bean id="foo" class="org.springframework.aop.framework.ProxyFactoryBean" p:proxyInterfaces="advice.advice.Foo" p:target-ref="target" p:interceptorNames="beforeAdvice,afterAdvice,aroundAdvice" /> </beans>
8.测试代码
package advice.advice; import org.aopalliance.intercept.MethodInterceptor; import org.springframework.aop.AfterReturningAdvice; import org.springframework.aop.BeforeAdvice; import org.springframework.aop.framework.ProxyFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainTest { public static void main(String[] args) { System.out.println("------xml配置风格实现之前增强-------"); // ----------xml文件方式实现前置增强 // 文件路径 String path = "config/advice-advice.xml"; // 加载配置文件 ApplicationContext context = new ClassPathXmlApplicationContext(path); // 获取Bena对象 Foo fooXml = (Foo) context.getBean("foo"); // 调用play方法,查看是否实现前置通知 fooXml.play("jing"); System.out.println("------java风格实现之前增强-------"); // ----- 实现接口方式实现前置增强 // 创建增强的兑仓 Foo foo = new FooImpl(); // 创建前置增强的接口,切入点 // 这里可以实现多个增强的切入点 BeforeAdvice beforeAdvice = new advice.advice.BeforeAdvice(); // 创建增强的代理器 ProxyFactory proxyFactory = new ProxyFactory(); // 设置代理目标 proxyFactory.setTarget(foo); // 添加代理切口,可以添加多个切口 proxyFactory.addAdvice(beforeAdvice); // 获取代理的器放回的对象 Foo fooAdvice = (Foo) proxyFactory.getProxy(); // 调用play方法,查看是否实现前置通知 fooAdvice.play("gaosi"); System.out.println("------后置增强增强-------"); // -------后置增强 // 切入后置增强的切入点 AfterReturningAdvice afterReturningAdvice = new AfterAdvice(); // 增加切入点 proxyFactory.addAdvice(afterReturningAdvice); // 获取添加增强后的对象 Foo afterAdviceFoo = (Foo) proxyFactory.getProxy(); afterAdviceFoo.play("lg"); System.out.println("-----环绕增强------"); // 创建环绕增强的切面 MethodInterceptor around = new AroundAdvice(); // 添加环绕增强的切点 proxyFactory.addAdvice(around); // 获取增加切点的对象 Foo aroundFoo = (Foo) proxyFactory.getProxy(); aroundFoo.play("jl"); } }
运行结果
10.Introdutions引介增强:
Introdutions是允许一个切面声明一个实现指定的接口的通知对象,并且提供一个接口实现来代理这些对象。与advice的区别在于,advice是方法级别的增强,Introdutions是类级别的增强。
可以参考 introdutions增强
相关推荐
SSH2 登录与 Spring AOP 拦截是两种在 IT 领域中常见的技术,主要用于提升系统安全性和管理效率。SSH2(Secure Shell version 2)是一种网络协议,用于提供安全的远程登录和数据传输,而 Spring AOP(Aspect ...
8. **优势**:SSH整合的优势在于,Spring的DI和AOP可以提高代码的可测试性和可维护性;Struts2提供了强大的MVC支持,简化了前端页面与后台的交互;而Hibernate则简化了数据库操作,使得开发者可以专注于业务逻辑。 ...
- 配置Spring AOP:在Spring配置文件中启用AOP支持,并配置切入点表达式。 - 定义切面:创建一个类作为切面,定义通知方法,并使用注解@Aspect来标识。 - 配置通知:使用@Before、@After、@AfterReturning、@...
在Spring的XML配置文件中,我们需要定义`<aop:config>`元素来开启AOP支持,然后创建`<aop:aspect>`元素来定义切面。切点通常通过`<aop:pointcut>`定义,并通过`id`属性给它命名。通知则通过`<aop:before>`、`<aop:...
SSH-AOP笔记主要涵盖的是Spring、Struts和Hibernate三大框架集成使用时,如何结合Aspect Oriented Programming(面向切面编程)的理念进行应用增强。在Java企业级开发中,SSH是常用的MVC架构,而AOP则是一种编程范式...
### SSH总结之Spring详解 #### 一、Spring框架概述 Spring框架是一个开源的轻量级企业级应用框架,主要由核心容器、数据访问/集成、Web、AOP(面向切面编程)、工具、测试、消息和REST等功能模块组成。Spring的核心...
标题中的"SSH学习记录(4)-AOP测试"指的是在软件开发中对Spring、Struts和Hibernate这三大框架(简称SSH)的第四部分学习,主要关注的是AOP(面向切面编程)的测试方面。AOP是编程的一种设计模式,它允许程序员定义...
在IT行业中,SSH和AOP是两个非常重要的概念,尤其在Java开发领域。SSH是指Spring、Struts和Hibernate这三个开源框架的首字母缩写,它们分别负责应用的依赖注入、MVC模式实现以及对象关系映射。AOP则是面向切面编程,...
在不使用注解的情况下,可以在Spring的配置文件中通过<aop:config>和<aop:advisor>元素来声明切面。这种方式需要显式地定义切点表达式、通知类型以及通知的执行逻辑。 6. **AOP的应用场景** - **事务管理**:...
NULL 博文链接:https://linres.iteye.com/blog/281221
2. 开启AOP代理:在Spring配置文件中,通过`<aop:config>`标签开启AOP支持,并可以定义切入点表达式(pointcut expression)和通知类型。 3. 定义切面:你可以使用Spring的`@Aspect`注解来定义一个切面类,然后在类...
SSH(Spring、Struts2、Hibernate)是一个经典的Java Web开发框架,它整合了Spring的IoC(Inversion of Control,控制反转)和AOP(Aspect-Oriented Programming,面向切面编程)功能,Struts2作为MVC(Model-View-...
1. 静态代理(XML定义):通过Spring的`<aop:config>`标签来配置切面,包括定义切入点表达式和通知类型。 2. 动态代理(基于注解):使用`@Aspect`注解定义切面,`@Before`、`@After`、`@Around`等注解定义通知,...
【SSH架构学习之Spring】 SSH(Struts、Spring、Hibernate)是Java开发中常见的三大框架组合,用于构建企业级Web应用程序。在这个主题中,我们主要关注Spring框架的学习。Spring作为一个全面的企业级应用开发框架,...
SSH和Spring框架是Java开发中的两个重要工具,它们在企业级应用开发中占据了核心地位。SSH,是由Struts2、Spring和Hibernate三个框架组成的集成解决方案,而Spring则是一个全面的后端开发框架,包含了多种功能模块。...
通过学习和实践这些SSH+AOP的资料源码,开发者可以提升自己在Java Web开发领域的技能,理解如何利用Spring管理依赖,使用Struts处理Web请求,借助Hibernate操作数据库,以及如何运用AOP来增强代码的灵活性和可维护性...
SSH(Struts、Spring、Hibernate)是一个经典的Java Web开发框架组合,其中Spring是核心,它负责管理和协调应用程序的各个部分。本资源提供了Spring框架所需的基本jar包,这些jar包是构建基于Spring的应用程序的基础...
SSH框架是Java开发中常用的三大框架集成,包括Struts2、Spring和Hibernate。这个压缩包提供了搭建SSH框架所需的所有jar包和配置文件,使得开发者能够快速构建基于这三大框架的应用。 Struts2作为MVC(Model-View-...
4. `<aop:before>`、`<aop:after>`、`<aop:around>`、`<aop:after-returning>`、`<aop:after-throwing>`:这些标签分别定义了在目标方法执行前、执行后(无论是否抛出异常)、环绕执行、正常返回后和抛出异常后执行...
SSH框架整合是Java Web开发中常见的一种技术栈,由Spring、Hibernate和Struts2三个开源框架组合而成。这个组合提供了一种高效、灵活且可扩展的解决方案,用于构建企业级的Web应用程序。以下是对SSH框架整合及其中...