Spring学习十五----------Spring AOP API的Pointcut、advice及 ProxyFactoryBean相关内容
© 版权声明:本文为博主原创文章,转载请注明出处
实例:
1.项目结构

2.pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.spring</groupId>
<artifactId>Spring-AOP-API</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Spring-AOP-API Maven Webapp</name>
<url>http://maven.apache.org</url> <properties>
<spring.version>4.3.8.RELEASE</spring.version>
</properties> <dependencies>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- Spring Core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies> <build>
<finalName>Spring-AOP-API</finalName>
</build>
</project>
3.BizLogic.java
package org.spring.aop.api;
public interface BizLogic {
String save();
String saveEx();
}
4.BizLogicImpl.java
package org.spring.aop.api;
public class BizLogicImpl implements BizLogic {
public String save() {
System.out.println("BizLogicImpl:BizLogicImpl save.");
return "BizLogicImpl save";
}
public String saveEx() {
System.out.println("BizLogicImpl:BizLogicImpl save.");
throw new RuntimeException();
}
}
5.CustomBeforeAdvice
package org.spring.aop.api;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class CustomBeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("CustomBeforeAdvice:" + method.getName() + " " +
target.getClass().getName());
}
}
6.CustomAfterReturnAdvice.java
package org.spring.aop.api;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class CustomAfterReturnAdvice implements AfterReturningAdvice {
public void afterReturning(Object returnValue, Method method, Object[] args, Object target)
throws Throwable {
System.out.println("CustomAfterReturnAdvice:" + method.getName() + " "
+ target.getClass().getName() + " " + returnValue);
}
}
7.CustomThrowsAdvice.java
package org.spring.aop.api;
import java.lang.reflect.Method;
import org.springframework.aop.ThrowsAdvice;
public class CustomThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(Exception ex) throws Throwable {
System.out.println("CustomThrowsAdvice afterThrowing 1");
}
public void afterThrowing(Method method, Object[] args, Object target, Exception ex)
throws Throwable {
System.out.println("CustomThrowsAdvice afterThrowing 2:" + method.getName() + " "
+ target.getClass().getName());
}
}
8.CustomMethodInterceptor.java
package org.spring.aop.api; import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; public class CustomMethodInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println("CustomMethodInterceptor 1:" + invocation.getMethod().getName()
+ " " + invocation.getStaticPart().getClass().getName());
Object obj = invocation.proceed();
System.out.println("CustomMethodInterceptor 2:" + obj);
return obj; } }
9.Lockable.java
package org.spring.aop.api.introduction; /**
* 接口
*
*/
public interface Lockable { void lock(); void unlock(); boolean locked(); }
10.LockMixin.java
package org.spring.aop.api.introduction; import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor; /**
* 实现类
*
*/
public class LockMixin extends DelegatingIntroductionInterceptor implements Lockable { private static final long serialVersionUID = 1L; private boolean locked; public void lock() { this.locked = true; } public void unlock() { this.locked = false; } public boolean locked() { return this.locked; } /**
* 被锁定后不能使用setter方法改变值
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable { if(locked && invocation.getMethod().getName().indexOf("set") == 0){
throw new RuntimeException();
}
return super.invoke(invocation); } }
11.LockMixinAdvisor.java
package org.spring.aop.api.introduction; import org.springframework.aop.support.DefaultIntroductionAdvisor; /**
* Introduction,在不改变代码的情况下,添加一个父类
*
*/
public class LockMixinAdvisor extends DefaultIntroductionAdvisor { private static final long serialVersionUID = 1L; public LockMixinAdvisor() { super(new LockMixin(), Lockable.class); } }
12.Spring-aop-api.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- Before advice
-一个简单的通知类型
-只是进方法之前被调用,不需要MethodInvocation对象
-前置通知可以在连接点执行之前插入自定义行为,但不能改变返回值
-->
<bean id="customBeforeAdvice" class="org.spring.aop.api.CustomBeforeAdvice"/> <!-- Throws advice
-如果连接点抛出异常,throws advice在连接点返回后被调用
-如果throws-advice的方法抛出异常,那么它将覆盖原有异常
-接口org.springframework.aop.ThrowsAdvice不包含任何方法,仅仅是一个声明,实现类需要实现类似下面的方法
-void afterThrowing([Method, args, target], ThrowableSubclass)
-->
<bean id="customThrowsAdvice" class="org.spring.aop.api.CustomThrowsAdvice"/> <!-- After Returning advice
-后置通知必须实现org.springframework.aop.AfterReturningAdvice几口
-可以访问返回值(但不能进行修改)、被调用的方法、方法的参数和目标
-如果抛出异常,将会抛出拦截器链,替代返回值
-->
<bean id="customAfterReturnAdvice" class="org.spring.aop.api.CustomAfterReturnAdvice"/> <!-- Interception around advice
-Spring的切入点模型使得切入点可以独立与advice重用,以针对不同的advice可以使用相同的切入点
-->
<bean id="customMethodInterceptor" class="org.spring.aop.api.CustomMethodInterceptor"/> <!-- Introduction advice
-Spring把引入通知作为一种特殊的拦截通知
-需要IntroductionAdvisor和IntroductionInterceptor
-仅适用于类,不能和任何切入点一起使用
-实例:如果调用lock()方法,希望所有的setter方法抛出LockedException异常。
-代码:Lockalbe.java LockMixin.java LockMixinAdvisor.java
-->
<!-- Advisor API
-Advisor是仅包含一个切入点表达式关联的单个通知的方面
-除了introductions,advisor可以用于任何通知
-org.springframework.aop.support.DefaultIntroductionAdvisor是最常用的advisor类,
它可以与MethodInterceptor,BeforeAdvice或者ThrowsAdvice一起使用
-它可以混合在Spring同一个AOP代理的advisor和advice
--> <!-- 当使用方式三时,屏蔽该bean的定义 -->
<!-- <bean id="bizLogicImplTarget" class="org.spring.aop.api.BizLogicImpl"/> --> <!-- ###########################方式一:使用pointcutBean开始############################# -->
<!-- 根据方法名匹配切入点pointcut -->
<!-- <bean id="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedNames">成员变量,匹配的方法名集合
<list>
<value>sa*</value>
</list>
</property>
</bean> <bean id="defaultAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="customBeforeAdvice"/>接入点通知,若非接入点,则该通知不生效
<property name="pointcut" ref="pointcutBean"/>接入点
</bean> --> <!-- ProxyFactoryBean
-创建Spring AOP代理的基本方法是使用org.springframework.aop.framework.ProxyFactoryBean
-这可以完全控制切入点和通知(advice)以及它们的顺序
-ProxyFactoryBean实现里getObject()方法创建一个AOP代理包装一个目标对象
-使用ProxyFactoryBean或者其它IOC相关类来创建AOP代理的最重要的好处是通知和切入点也可以由IOC来管理
-被代理类没有实现任何接口,使用CGLIB代理,否则JDK代理
-通过设置proxyTargetClass为true,可强制使用CGLIB
-如果目标类实现了一个(或者多个)接口,那么创建代理的类型将依赖ProxyFactoryBean的配置
-如果ProxyFactoryBean的proxyInterfaces属性设置为一个或多个全限定接口名,基于JDK的代理将被创建
-如果ProxyFactoryBean的proxyInterfaces属性没有被设置,但是目标类实现了一个(或者更多)接口,那么proxyInterfaces
将自动检测到这个目标类已经实现了至少一个接口,创建一个基于JDK的代理
-->
<!-- <bean id="bizLogicImpl" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">为该类创建代理,由ProxyFactoryBean自己去判断是否实现了接口
<ref bean="bizLogicImplTarget"/>
</property>
<property name="interceptorNames">执行该代理的时候执行的interceptor
<list>
<value>defaultAdvisor</value>
<value>customAfterReturnAdvice</value>
<value>customMethodInterceptor</value>
<value>customThrowsAdvice</value>
</list>
</property>
</bean> -->
<!-- ###############################方式一结束######################################### -->
<!-- ############################方式二:使用pointcutBean开始############################ -->
<!-- <bean id="bizLogicImpl" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">直接指定接口
<value>org.spring.aop.api.BizLogic</value>
</property>
<property name="target">为该类创建代理,因为直接指定了接口,所以肯定是使用JDK代理
<ref bean="bizLogicImplTarget"/>
</property>
<property name="interceptorNames">执行该代理的时候执行的interceptor
<list>
<value>customBeforeAdvice</value>
<value>customAfterReturnAdvice</value>
<value>customMethodInterceptor</value>
<value>customThrowsAdvice</value>
</list>
</property>
</bean> -->
<!-- ###############################方式二结束######################################### -->
<!-- ##############################方式三:使用匿名内部Bean############################### -->
<bean id="bizLogicImpl" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces"><!-- 直接指定接口 -->
<value>org.spring.aop.api.BizLogic</value>
</property>
<property name="target"><!-- 上面可以直接使用bean id获取bean对象,此时该bean对象没有被代理,配置的advice不会被执行 -->
<bean class="org.spring.aop.api.BizLogicImpl"/>
</property>
<property name="interceptorNames"><!-- 执行该代理的时候执行的interceptor -->
<list>
<value>customBeforeAdvice</value>
<value>customAfterReturnAdvice</value>
<value>customMethodInterceptor</value>
<value>customThrowsAdvice</value>
</list>
<!-- 使用global advisors
-用*做通配,匹配所有拦截器加入通知链
此处只会执行customMethodInterceptor,因为只有该advice实现了Interceptor接口
-->
<!-- <list>
<value>custom*</value>
</list> -->
</property>
</bean>
<!-- ###############################方式三结束######################################### -->
<!-- ##############################方式四:简化的proxy定义############################### -->
<!-- 简化的proxy定义
-使用父子bean定义以及内部bean定义,可能会带来更清洁和更简洁的代理定义
-->
<!-- <bean id="baseProxyBean" class="org.springframework.aop.framework.ProxyFactoryBean"
lazy-init="true" abstract="true"/> <bean id="bizLogicImpl" parent="baseProxyBean">
<property name="proxyInterfaces">直接指定接口
<value>org.spring.aop.api.BizLogic</value>
</property>
<property name="target">上面可以直接使用bean id获取bean对象,此时该bean对象没有被代理,配置的advice不会被执行
<bean class="org.spring.aop.api.BizLogicImpl"/>
</property>
<property name="interceptorNames">执行该代理的时候执行的interceptor
<list>
<value>customBeforeAdvice</value>
<value>customAfterReturnAdvice</value>
<value>customMethodInterceptor</value>
<value>customThrowsAdvice</value>
</list>
</property>
</bean> -->
<!-- ###############################方式四结束######################################### --> </beans>
13.TestBase.java
package org.spring.aop.api.test; import org.junit.After;
import org.junit.Before;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.StringUtils; public class TestBase { private ClassPathXmlApplicationContext context;
private String springXmlPath; /**
* 无参构造器
*/
public TestBase() { } /**
* 含参构造器,初始化spring配置文件路径
*
* @param springXmlPath
* spring配置文件路径
*/
public TestBase(String springXmlPath) { this.springXmlPath = springXmlPath; } /**
* 初始化spring配置文件并加载到IOC容器中
*/
@Before
public void before() { if(StringUtils.isEmpty(springXmlPath)) {
springXmlPath = "classpath:spring-*.xml";
}
context = new ClassPathXmlApplicationContext(springXmlPath.split("[,\\s]+"));
context.start(); } /**
* 销毁IOC容器
*/
@After
public void after() { if(context != null){
context.destroy();
} } /**
* 根据bean ID获取bean对象
*
* @param beanId
* bean ID
* @return
*/
public Object getBean(String beanId) { return context.getBean(beanId); } }
14.TestSpringAOPAPI.java
package org.spring.aop.api.test; import org.junit.Test;
import org.spring.aop.api.BizLogic; public class TestSpringAOPAPI extends TestBase { /**
* 通过构造器初始化spring配置文件
*/
public TestSpringAOPAPI() { super("classpath:spring-aop-api.xml"); } /**
* 测试正常方法
*/
@Test
public void testSave() { BizLogic logic = (BizLogic) super.getBean("bizLogicImpl");
logic.save(); } /**
* 测试存在异常的方法
*/
@Test
public void testsaveEx() { BizLogic logic = (BizLogic) super.getBean("bizLogicImpl");
logic.saveEx(); } }
15.效果预览
15.1 执行testSave方法

15.2 执行testsaveEx方法

说明:其他几种方式已在spring-aop-api.xml中注明,可自行测试。
参考:http://www.imooc.com/video/4597
http://www.imooc.com/video/4598
http://www.imooc.com/video/4599
Spring学习十五----------Spring AOP API的Pointcut、advice及 ProxyFactoryBean相关内容的更多相关文章
- Spring学习(十五)----- Spring AOP通知实例 – Advice
Spring AOP(面向方面编程)框架,用于在模块化方面的横切关注点.简单得说,它只是一个拦截器拦截一些过程,例如,当一个方法执行,Spring AOP 可以劫持一个执行的方法,在方法执行之前或之后 ...
- spring学习 十五 spring的自动注入
一 :在 Spring 配置文件中对象名和 ref=”id” ,id 名相同使用自动注入,可以不配置<property/>,对应的注解@Autowired的作用 二: 两种配置办法 (1 ...
- Spring学习十四----------Spring AOP实例
© 版权声明:本文为博主原创文章,转载请注明出处 实例 1.项目结构 2.pom.xml <project xmlns="http://maven.apache.org/POM/4.0 ...
- spring boot(十五)spring boot+thymeleaf+jpa增删改查示例
快速上手 配置文件 pom包配置 pom包里面添加jpa和thymeleaf的相关包引用 <dependency> <groupId>org.springframework.b ...
- Spring 学习十五 AOP
http://www.hongyanliren.com/2014m12/22797.html 1: 通知(advice): 就是你想要的功能,也就是安全.事物.日子等.先定义好,在想用的地方用一下.包 ...
- Spring学习(十九)----- Spring的五种事务配置详解
前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. ...
- spring学习 十四 注解AOP 通知传递参数
我们在对切点进行增强时,不建议对切点进行任何修改,因此不加以使用@PointCut注解打在切点上,尽量只在Advice上打注解(Before,After等),如果要在通知中接受切点的参数,可以使用Jo ...
- Spring学习(十八)----- Spring AOP+AspectJ注解实例
我们将向你展示如何将AspectJ注解集成到Spring AOP框架.在这个Spring AOP+ AspectJ 示例中,让您轻松实现拦截方法. 常见AspectJ的注解: @Before – 方法 ...
- Spring学习(十六)----- Spring AOP实例(Pointcut(切点),Advisor)
在上一个Spring AOP通知的例子,一个类的整个方法被自动拦截.但在大多数情况下,可能只需要一种方式来拦截一个或两个方法,这就是为什么引入'切入点'的原因.它允许你通过它的方法名来拦截方法.另外, ...
随机推荐
- sql中的like和正则的区别
like,模糊查询,更多的是用于匹配已知的字符,比如查询该字段含有1的记录,like ‘%1%’:但是如果要匹配不确定的,但是一个系列的字符,比如数字,最好用regexpselect * from t ...
- 洛谷 P1342 请柬
题目描述 在电视时代,没有多少人观看戏剧表演.Malidinesia古董喜剧演员意识到这一事实,他们想宣传剧院,尤其是古色古香的喜剧片.他们已经打印请帖和所有必要的信息和计划.许多学生被雇来分发这些请 ...
- VIJOS【1234】口袋的天空
背景 小杉坐在教室里,透过口袋一样的窗户看口袋一样的天空. 有很多云飘在那里,看起来很漂亮,小杉想摘下那样美的几朵云,做成棉花糖. 描述 给你云朵的个数N,再给你M个关系,表示哪些云朵可以连在一起. ...
- 最近发的一些csdn下载资源
原文发布时间为:2009-11-02 -- 来源于本人的百度文章 [由搬家工具导入] http://wjwu1988.download.csdn.net/treeview的datasource类 ...
- C#byte怎么转成图片
这个其实很简单我给大家提供一个方法吧 /// <summary> /// 字节数组生成图片 /// </summary> /// <param name="By ...
- 【转载】Outlook2010 移动数据文件到其它地方
您可以将数据文件移到计算机的其他文件夹中.移动文件的一个原因在于可使备份更容易并且可以让默认的outlook邮件文件不在存在C盘,导致装系统不见或者文件过大而撑死了C盘.例如,如果数据 ...
- 余秋雨的话(与OI无关)
余秋雨的话 1.假如你想要一件东西,就放它走.它若能回来找你,就永远属于你:它若不回来,那根本就不是你的. 2. 一个人会落泪,是因为痛:一个人之所以痛,是因为在乎:一个人之所以在乎,是因为有感觉:一 ...
- Web模糊测试工具Powerfuzzer
Web模糊测试工具Powerfuzzer Powerfuzzer是Kali Linux自带的一款Web模糊测试工具.该工具基于各种开源模糊测试工具构建,集成了大量安全信息.该工具高度智能化,它能根 ...
- JSP介绍与语法-java之JSP学习第一天(非原创)
文章大纲 一.JSP 简介二.JSP 生命周期三.JSP 语法四.学习资料下载五.参考文章 一.JSP 简介 1. 什么是Java Server Pages? JSP全称Java Server P ...
- shell脚本 linux脚本
linux:shell 脚本 如果判断当前时间 是不是12点之前 用date命令先取得当前的时间(仅取小时数) : date '+%H' #按24小时制取hour (00..23) 然后与12 ...