转载自:http://chenjumin.iteye.com/blog/364948
一、基础接口和类
1、Person接口的源码
- public interface Person {
- public void info();
- public void show(String message);
- }
public interface Person { public void info(); public void show(String message); }
2、PersonImpl类的源码
- public class PersonImpl implements Person {
- private String name;
- private int age;
- public void setName(String name) {
- this.name = name;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public void info() {
- System.out.println("\t我叫" + name + ",今年" + age + "岁。");
- }
- public void show(String message) {
- System.out.println(message);
- }
- }
public class PersonImpl implements Person { private String name; private int age; public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public void info() { System.out.println("\t我叫" + name + ",今年" + age + "岁。"); } public void show(String message) { System.out.println(message); } }
3、bean的配置
- <!-- 目标对象 -->
- <bean id="personTarget" class="com.cjm.aop.PersonImpl">
- <property name="name" value="Raymond.chen"/>
- <property name="age" value="30"/>
- </bean>
<!-- 目标对象 --> <bean id="personTarget" class="com.cjm.aop.PersonImpl"> <property name="name" value="Raymond.chen"/> <property name="age" value="30"/> </bean>
二、Spring AOP支持的通知类型
一)环绕通知(Around advice)
实现环绕通知需要实现org.aopalliance.intercept.MethodInterceptor接口。
1、PersonAroundAdvice类的源码
- public class PersonAroundAdvice implements MethodInterceptor {
- public Object invoke(MethodInvocation invocation) throws Throwable {
- System.out.println("AroundAdvice:方法调用前");
- //不要忘记调用invocation的proceed方法哦
- Object result = invocation.proceed();
- System.out.println("AroundAdvice:方法调用后");
- return result;
- }
- }
public class PersonAroundAdvice implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("AroundAdvice:方法调用前"); //不要忘记调用invocation的proceed方法哦 Object result = invocation.proceed(); System.out.println("AroundAdvice:方法调用后"); return result; } }
2、bean配置
- <bean id="personAroundAdvice" class="com.cjm.aop.PersonAroundAdvice"/>
- <!-- 代理工厂bean -->
- <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="proxyInterfaces" value="com.cjm.aop.Person"/>
- <property name="target" ref="personTarget"/>
- <property name="interceptorNames">
- <list>
- <value>personAroundAdvice</value>
- </list>
- </property>
- </bean>
<bean id="personAroundAdvice" class="com.cjm.aop.PersonAroundAdvice"/> <!-- 代理工厂bean --> <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="com.cjm.aop.Person"/> <property name="target" ref="personTarget"/> <property name="interceptorNames"> <list> <value>personAroundAdvice</value> </list> </property> </bean>
3、测试代码
- ApplicationContext context = new FileSystemXmlApplicationContext("classpath:com/cjm/aop/beans.xml");
- Person p = (Person)context.getBean("person"); //注意这里是代理工厂Bean的ID
- p.info();
ApplicationContext context = new FileSystemXmlApplicationContext("classpath:com/cjm/aop/beans.xml"); Person p = (Person)context.getBean("person"); //注意这里是代理工厂Bean的ID p.info();
二)前置通知(Before advice)
实现前置通知需要实现org.springframework.aop.MethodBeforeAdvice接口。
1、PersonBeforeAdvice类的源码
- public class PersonBeforeAdvice implements MethodBeforeAdvice {
- public void before(Method method, Object[] args, Object target) throws Throwable {
- System.out.println("BeforeAdvice:方法调用前");
- }
- }
public class PersonBeforeAdvice implements MethodBeforeAdvice { public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println("BeforeAdvice:方法调用前"); } }
2、bean配置
- <bean id="personBeforeAdvice" class="com.cjm.aop.PersonBeforeAdvice"/>
- <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="proxyInterfaces" value="com.cjm.aop.Person"/>
- <property name="target" ref="personTarget"/>
- <property name="interceptorNames">
- <list>
- <value>personBeforeAdvice</value>
- </list>
- </property>
- </bean>
<bean id="personBeforeAdvice" class="com.cjm.aop.PersonBeforeAdvice"/> <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="com.cjm.aop.Person"/> <property name="target" ref="personTarget"/> <property name="interceptorNames"> <list> <value>personBeforeAdvice</value> </list> </property> </bean>
三)返回后通知(After Returning advice)
实现返回后通知需要实现org.springframework.aop.AfterReturningAdvice接口。
1、PersonAfterReturningAdvice类的源码
- public class PersonAfterReturningAdvice implements AfterReturningAdvice {
- public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
- System.out.println("AfterReturningAdvice:方法调用后");
- }
- }
public class PersonAfterReturningAdvice implements AfterReturningAdvice { public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("AfterReturningAdvice:方法调用后"); } }
2、bean配置
- <bean id="personAfterReturningAdvice" class="com.cjm.aop.PersonAfterReturningAdvice"/>
- <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="proxyInterfaces" value="com.cjm.aop.Person"/>
- <property name="target" ref="personTarget"/>
- <property name="interceptorNames">
- <list>
- <value>personAfterReturningAdvice</value>
- </list>
- </property>
- </bean>
<bean id="personAfterReturningAdvice" class="com.cjm.aop.PersonAfterReturningAdvice"/> <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="com.cjm.aop.Person"/> <property name="target" ref="personTarget"/> <property name="interceptorNames"> <list> <value>personAfterReturningAdvice</value> </list> </property> </bean>
3、以上的配置中,通知对目标对象的所有方法都会起作用。如果需要过滤掉一部分方法,可以用正则表达式切入点配置器或者方法名匹配切入点配置器实现。
- <!-- 通知与正则表达式切入点一起配置 -->
- <!-- Advisor等于切入点加通知 -->
- <!-- 方法名匹配切入点配置器:org.springframework.aop.support.NameMatchMethodPointcutAdvisor -->
- <bean id="personPointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
- <property name="advice" ref="personAfterReturningAdvice"/>
- <property name="patterns">
- <list>
- <value>.*info.*</value>
- </list>
- </property>
- </bean>
- <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="proxyInterfaces" value="com.cjm.aop.Person"/>
- <property name="target" ref="personTarget"/>
- <property name="interceptorNames">
- <list>
- <value>personPointcutAdvisor</value>
- </list>
- </property>
- </bean>
<!-- 通知与正则表达式切入点一起配置 --> <!-- Advisor等于切入点加通知 --> <!-- 方法名匹配切入点配置器:org.springframework.aop.support.NameMatchMethodPointcutAdvisor --> <bean id="personPointcutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice" ref="personAfterReturningAdvice"/> <property name="patterns"> <list> <value>.*info.*</value> </list> </property> </bean> <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="com.cjm.aop.Person"/> <property name="target" ref="personTarget"/> <property name="interceptorNames"> <list> <value>personPointcutAdvisor</value> </list> </property> </bean>
四)异常通知(Throws advice)
当连接点抛出异常时,异常通知被调用。实现异常通知需要实现org.springframework.aop.ThrowsAdvice接口,该接口不包含任何方法,但在实现该接口时必须实现如下形式的方法:
afterThrowing([Method], [args], [target], Throwable subclass)
可以实现一个或多个这样的方法。在这些方法中,只有第四个参数是必需的,前三个参数可选。
1、PersonThrowsAdvice类的源码
- public class PersonThrowsAdvice implements ThrowsAdvice {
- public void afterThrowing(FileNotFoundException ex){
- System.out.println("ThrowsAdvice >> FileNotFoundException:" + ex.toString());
- }
- public void afterThrowing(Object[] args, Exception ex){
- System.out.println("ThrowsAdvice >> Exception:" + ex.getMessage());
- }
- public void afterThrowing(Method method, Object[] args, Object target, Throwable ex){
- System.out.println("ThrowsAdvice >> Throwable:" + ex.getMessage());
- }
- }
public class PersonThrowsAdvice implements ThrowsAdvice { public void afterThrowing(FileNotFoundException ex){ System.out.println("ThrowsAdvice >> FileNotFoundException:" + ex.toString()); } public void afterThrowing(Object[] args, Exception ex){ System.out.println("ThrowsAdvice >> Exception:" + ex.getMessage()); } public void afterThrowing(Method method, Object[] args, Object target, Throwable ex){ System.out.println("ThrowsAdvice >> Throwable:" + ex.getMessage()); } }
2、bean配置
- <bean id="personThrowsAdvice" class="com.cjm.aop.PersonThrowsAdvice"/>
- <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="proxyInterfaces" value="com.cjm.aop.Person"/>
- <property name="target" ref="personTarget"/>
- <property name="interceptorNames">
- <list>
- <value>personThrowsAdvice</value>
- </list>
- </property>
- </bean>
<bean id="personThrowsAdvice" class="com.cjm.aop.PersonThrowsAdvice"/> <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="com.cjm.aop.Person"/> <property name="target" ref="personTarget"/> <property name="interceptorNames"> <list> <value>personThrowsAdvice</value> </list> </property> </bean>
五)引入通知(Introduction advice)
引入通知是一种特殊的通知,它能将新的成员变量、成员方法引入到目标类中。它不能作用于任何切入点,因为它只作用于类层次,而不是方法层次。实现引入通知需要实现IntroductionAdvisor和IntroductionInterceptor接口。
引入通知不能调用proceed方法。Advisor必须针对每个实例,并且是有状态的。
引入通知的效果类似于设计模式中的访问者模式(Visitor Pattern)。
1、Lockable接口的源码
- public interface Lockable {
- void lock();
- void unlock();
- boolean locked();
- }
public interface Lockable { void lock(); void unlock(); boolean locked(); }
2、LockableImpl类的源码
- public class LockableImpl extends DelegatingIntroductionInterceptor implements Lockable {
- private boolean locked;
- public void lock() {
- this.locked = true;
- }
- public void unlock() {
- this.locked = false;
- }
- public boolean locked() {
- return this.locked;
- }
- @Override
- public Object invoke(MethodInvocation invocation) throws Throwable {
- if(this.locked){
- throw new RuntimeException("加锁,无法执行");
- }
- //这里不能调用invocation的proceed方法
- //通常不需要改写invoke方法,直接调用父类的该方法即可
- return super.invoke(invocation);
- }
- }
public class LockableImpl extends DelegatingIntroductionInterceptor implements Lockable { private boolean locked; public void lock() { this.locked = true; } public void unlock() { this.locked = false; } public boolean locked() { return this.locked; } @Override public Object invoke(MethodInvocation invocation) throws Throwable { if(this.locked){ throw new RuntimeException("加锁,无法执行"); } //这里不能调用invocation的proceed方法 //通常不需要改写invoke方法,直接调用父类的该方法即可 return super.invoke(invocation); } }
3、PersonIntroductionAdvice类的源码
- public class PersonIntroductionAdvice extends DefaultIntroductionAdvisor {
- public PersonIntroductionAdvice(){
- super(new LockableImpl(), Lockable.class);
- }
- }
public class PersonIntroductionAdvice extends DefaultIntroductionAdvisor { public PersonIntroductionAdvice(){ super(new LockableImpl(), Lockable.class); } }
4、bean配置
- <!-- Advice必须针对每个实例,所以scope要设为prototype -->
- <bean id="personIntroductionAdvice" class="com.cjm.aop.introduction.PersonIntroductionAdvice" scope="prototype"/>
- <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="proxyInterfaces" value="com.cjm.aop.Person"/>
- <property name="target" ref="personTarget"/>
- <property name="interceptorNames">
- <list>
- <value>personIntroductionAdvice</value>
- </list>
- </property>
- </bean>
<!-- Advice必须针对每个实例,所以scope要设为prototype --> <bean id="personIntroductionAdvice" class="com.cjm.aop.introduction.PersonIntroductionAdvice" scope="prototype"/> <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces" value="com.cjm.aop.Person"/> <property name="target" ref="personTarget"/> <property name="interceptorNames"> <list> <value>personIntroductionAdvice</value> </list> </property> </bean>
5、测试代码
- ApplicationContext context = new FileSystemXmlApplicationContext("classpath:com/cjm/aop/beans.xml");
- //获得目标bean的代理bean
- Person p = (Person)context.getBean("person");
- //执行代理bean的方法,此时并未调用lock方法,可以执行
- p.info();
- Lockable lockable = (Lockable)p;
- lockable.lock();
- //目标bean已被锁定,此处将抛出异常
- p.info();
相关推荐
Spring支持五种不同类型的通知:前置通知(Before)、后置通知(After)、返回通知(After Returning)、异常通知(After Throwing)和环绕通知(Around)。 3. **连接点(Join Point)**:连接点是在应用程序执行...
5. **代理(Proxy)**:Spring AOP通过JDK动态代理或CGLIB代理来创建一个目标对象的代理,以便在调用目标方法时插入通知。 实际操作中,我们可以使用注解来声明切面,例如`@Aspect`、`@Before`、`@After`等,也可以...
在Spring框架中,AOP的实现不仅增强了应用程序的灵活性,还提供了丰富的通知类型,便于开发者根据不同场景选择最合适的通知策略,从而构建更加高效、健壮的系统。理解并掌握AOP的概念和机制,对提高软件开发效率和...
Spring AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架的重要特性之一,它能够让我们在不修改原有代码的情况下,给程序中的一些功能增加额外的行为,例如日志、事务管理等。通过AOP,开发者可以将横...
- `spring_aop_annotation` 文件夹包含的是使用注解方式实现的 AOP 示例。在 Spring 中,AOP 允许开发者定义“切面”,将关注点(如日志、事务管理)与业务逻辑分离。通过 @Aspect 注解定义切面,@Before、@After、...
"尚硅谷佟刚Spring完整代码"是一个集合了全面Spring框架示例和教程的资源包,旨在帮助学习者深入理解和实践Spring框架的各种功能。这个压缩包包含的文件是开发者为了补充尚硅谷官网上的Spring代码而精心整理和完善的...
Spring框架是Java开发中的核心组件,它以依赖注入(Dependency Injection, DI)和面向切面编程(Aspect-Oriented Programming, AOP)为核心,极大地简化了企业级应用的开发过程。这份“Spring基础学习资料”涵盖了...
4. **AOP**:Spring的AOP允许开发者定义“切面”,这些切面可以包含通知(advice),即在特定连接点(join point)执行的代码,比如方法调用前或后。AOP用于日志记录、事务管理、权限检查等场景。 5. **数据访问...
Spring框架是Java开发中广泛使用的轻量级框架,以其依赖注入(Dependency Injection,简称DI)和面向切面编程(Aspect-Oriented Programming,简称AOP)的核心特性,极大地简化了企业级应用的开发。以下是对Spring...
通过阅读源码,我们可以学习如何定义切面、切入点表达式和通知类型,并理解Spring如何在运行时生成代理对象以实现AOP功能。 再者,Spring的事务管理也是其关键特性之一。Spring提供了编程式和声明式事务管理两种...
Spring框架是Java开发中不可或缺的一部分,它以其强大的依赖注入(DI)和面向切面编程(AOP)功能而闻名。面试中,Spring相关的知识点通常包括其核心概念、配置方式、AOP原理、事务管理、MVC模块、Spring Boot以及...
这个“Spring面试专题及答案整理文档”包含了Spring框架的重要知识点,是准备Spring面试和深入理解Spring技术体系的良好资料。 1. **依赖注入(DI)** - DI是Spring的核心,它允许开发者在运行时通过XML配置或注解...
根据提供的信息,我们可以推断这份文档是关于Spring框架的一个中文参考文档,主要涵盖了Spring的核心概念和技术要点。下面将根据给出的信息来整理并扩展...希望以上整理的知识点能帮助您更好地理解和使用Spring框架。
标签中提到了“源码”和“工具”,这意味着内容可能包含如何使用各种工具(如IDEA、Git等)来阅读和理解Spring的源代码。源码阅读对于开发者来说是一项重要技能,它涉及理解类结构、方法调用、设计模式等。而工具的...
根据提供的文件内容,我们可以整理出一系列与Spring框架相关的知识点,涉及Spring的基本概念、Spring与其它技术的集成方式、以及Spring支持的各种模式等。下面将详细展开这些知识点。 ### Spring框架概述 Spring是...
6. **spring-aop.jar**:提供 AOP 支持,可以创建切面和通知,实现如日志记录、事务管理等功能。 7. **spring-jdbc.jar** 和 **spring-tx.jar**:数据库事务管理和 JDBC 支持,对于需要数据库操作的应用,这两个库...
aop|[aop,正则,前置通知,后置通知,环绕通知](https://github.com/smltq/spring-boot-demo/blob/master/aop/HELP.md) data-redis|[lettuce,redis,session redis,YAML配置,连接池,对象存储]...
4. **资源加载**:Spring提供了`Resource`接口用于处理各种类型的资源,如文件、URL等。`ResourceLoader`用于获取`Resource`,而`BeanDefinition`用于存储Bean的元数据,包括其依赖和其他配置信息。`...
- **AOP**:面向切面编程,理解切点、通知、代理等概念,以及Spring AOP的实现方式。 - **Spring Boot**:快速开发特性,如自动配置、Actuator监控、Spring Data JPA等。 - **Spring Cloud**:服务治理、配置中心...