Spring框架中的AOP技术----配置文件方式
1、AOP概述
AOP技术即Aspect Oriented Programming的缩写,译为面向切面编程。AOP是OOP的一种延续,利用AOP技术可以对业务逻辑的各个部分进行隔离,从使得业务逻辑各部分之间的耦合性降低,提高程序的可重用性,同时提高了开发的效率。
AOP采用横向抽取机制,取代了传统纵向继承体系重复性代码,AOP可以在不修改源代码的前提下,对程序进行增强。
2、AOP技术的底层实现
- 基于jdk的动态代理:必须是面向接口的,只有实现了具体接口的类才能生成代理对象
- 基于CGLIB动态代理:对于没有实现接口的类,也可以产生代理,产生这个类的子类的方式
Spring的传统AOP中根据类是否实现接口而采用不同的代理方式,如果实现类接口,则使用jdk动态代理完成AOP,如果没有实现接口,采用CGLIB动态代理完成AOP。
JDK动态代理演示:
接口UserDao、实现类UserDaoImpl、动态代理类MyProxyUtils
package com.alphajuns.demo1;
public interface UserDao {
public void save();
public void update();
}
package com.alphajuns.demo1;
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("保存用户...");
}
@Override
public void update() {
System.out.println("修改用户...");
}
}
package com.alphajuns.demo1; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /*
* 使用JDK的方式生成动态代理
*/
public class MyProxyUtils { public static UserDao getProxy(final UserDao dao) {
// 使用Proxy类生成代理对象
UserDao proxy = (UserDao) Proxy.newProxyInstance(
dao.getClass().getClassLoader(),
dao.getClass().getInterfaces(),
new InvocationHandler() { @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("save".equals(method.getName())) {
System.out.println("记录日志...");
}
// 执行dao类中的方法
return method.invoke(dao, args);
}
}); // 返回代理对象
return proxy;
} }
CGLIB代理:
package com.alphajuns.demo2; import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; public class MyCglibUtils { /*
* 使用Cglib方法生成代理对象
*/
public static BookDaoImpl getProxy() {
Enhancer enhancer = new Enhancer();
// 设置父类
enhancer.setSuperclass(BookDaoImpl.class);
// 设置回调函数
enhancer.setCallback(new MethodInterceptor() {
// 代理对象的方法执行,回调函数的方法就会执行
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if ("save".equals(method.getName())) {
System.out.println("记录日志...");
}
// 正常执行
return methodProxy.invokeSuper(obj, args);
}
}); // 生成代理对象
BookDaoImpl proxy = (BookDaoImpl) enhancer.create();
return proxy;
} }
3、AOP相关术语
- JoinPoint(连接点):被拦截的点。Spring中,这些点是指方法,Spring只支持方法类型的连接点。
- Pointcut(切入点):对需要被拦截的JoinPoint的定义。
- Advice(通知/增强):拦截到JointPoint之后所要做的事情就是通知。通知分为前置通知、后置通知、异常通知、最终通知、环绕通知
- Introduction(引介):引介是一种特殊的通知,在不修改代码的前提下,Introduction可以在运行期为类动态地添加一些方法或field
- Target(目标对象):代理的目标对象
- Weaving(织入):是指增强应用到目标对象来创建新的代理对象的过程
- Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类
- Aspect(切面):切入点与通知的结合
4、XML方式AOP开发步骤
- 创建WEB项目,引入jar包
- 创建Spring配置文件,引入AOP的schema约束
- 创建包结构,编写具体的接口和实现类
- 将目标类配置到Spring配置文件中
- 定义切面类
- 在配置文件中定义切面类
- 在配置文件中完成AOP配置
- 测试
5、切入点表达式
切入点表达式在下面applicationContext2中以注释形式进行了介绍。
6、AOP通知类型
- 前置通知:在目标类的方法执行之前执行
- 后置通知:在目标类方法执行之后执行
- 异常抛出通知:在抛出异常后通知
- 环绕通知:方法执行前后都执行
7、AOP应用举例
接口CustomerDao、实现类CustomerDaoImpl、切面类MyAspectXml、Spring配置文件applicationContext、applicationContext2、applicationContext3
package com.alphajuns.demo3;
public interface CustomerDao {
public void save();
public void update();
}
package com.alphajuns.demo3;
public class CustomerDaoImpl implements CustomerDao {
@Override
public void save() {
System.out.println("保存客户...");
}
@Override
public void update() {
System.out.println("更新客户...");
}
}
package com.alphajuns.demo3; import org.aspectj.lang.ProceedingJoinPoint; /*
* 切面类:切入点+通知
*/
public class MyAspectXml { /*
* 通知(具体的增强)
*/
public void log() {
System.out.println("记录日志...");
} /*
* 最终通知:方法执行成功或出现异常,都会执行
*/
public void after() {
System.out.println("最终通知...");
} /*
* 后置通知:方法执行之后,执行后置通知,出现异常则不执行
*/
public void afterReturn() {
System.out.println("后置通知...");
} /*
* 环绕通知:方法执行之前和方法执行之后进行通知,默认情况下,目标对象的方法不执行。需要手动让目标对象的方法执行
*/
public void around(ProceedingJoinPoint joinPoint) {
System.out.println("环绕通知1...");
try {
// 手动让目标对象的方法执行
joinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("环绕通知2...");
} }
<?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.xsd"> <!-- bean definitions here --> <!-- 配置客户的dao -->
<bean id="customerDao" class="com.alphajuns.demo3.CustomerDaoImpl"/>
<!-- 配置切面类 -->
<bean id="myAspectXml" class="com.alphajuns.demo3.MyAspectXml"/>
<!-- 配置AOP -->
<aop:config>
<!-- 配置切面类:切入点+通知类型 -->
<aop:aspect ref="myAspectXml">
<!-- 配置前置通知 -->
<aop:before method="log" pointcut="execution(public void com.alphajuns.demo3.CustomerDaoImpl.save())"/>
</aop:aspect>
</aop:config> </beans>
<?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.xsd"> <!-- bean definitions here --> <!-- 配置客户的dao -->
<bean id="customerDao" class="com.alphajuns.demo3.CustomerDaoImpl"/>
<!-- 配置切面类 -->
<bean id="myAspectXml" class="com.alphajuns.demo3.MyAspectXml"/>
<!-- 配置AOP -->
<aop:config>
<!-- 配置切面类:切入点+通知类型 -->
<aop:aspect ref="myAspectXml">
<!-- 配置前置通知 -->
<!-- 切入点的表达式
1、execution() 固定的,不能不写
2、public 可以省略不写
3、void出可以用*替代,表示返回值类型任意,不能省略不写
4、包的简写方式
5、类的写法
6、方法的写法
7、方法的参数
-->
<!-- 完整写法 -->
<!-- <aop:before method="log" pointcut="execution(public void com.alphajuns.demo3.CustomerDaoImpl.save())"/> -->
<!-- public可以省略不写 -->
<!-- <aop:before method="log" pointcut="execution(void com.alphajuns.demo3.CustomerDaoImpl.save())"/> -->
<!-- void出用*替代 -->
<!-- <aop:before method="log" pointcut="execution(* com.alphajuns.demo3.CustomerDaoImpl.save())"/> -->
<!-- 包的写法 -->
<!-- <aop:before method="log" pointcut="execution(* com.alphajuns.demo3.CustomerDaoImpl.save())"/> -->
<!-- 包的写法 -->
<!-- <aop:before method="log" pointcut="execution(* *..*.CustomerDaoImpl.save())"/> -->
<!-- 类的写法 -->
<!-- <aop:before method="log" pointcut="execution(* com.alphajuns.demo3.*DaoImpl.save())"/> -->
<!-- 方法写法 -->
<!-- <aop:before method="log" pointcut="execution(* com.alphajuns.demo3.CustomerDaoImpl.*save())"/> -->
<!-- 方法的参数 -->
<aop:before method="log" pointcut="execution(* com.alphajuns.demo3.CustomerDaoImpl.*save(..))"/>
</aop:aspect>
</aop:config> </beans>
<?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.xsd"> <!-- bean definitions here --> <!-- 配置客户的dao -->
<bean id="customerDao" class="com.alphajuns.demo3.CustomerDaoImpl"/>
<!-- 配置切面类 -->
<bean id="myAspectXml" class="com.alphajuns.demo3.MyAspectXml"/>
<!-- 配置AOP -->
<aop:config>
<!-- 配置切面类:切入点+通知类型 -->
<aop:aspect ref="myAspectXml">
<!-- 配置前置通知 -->
<!-- <aop:before method="log" pointcut="execution(public void com.alphajuns.demo3.CustomerDaoImpl.save())"/> -->
<!-- 配置后置通知 -->
<!-- <aop:after method="log" pointcut="execution(public void com.alphajuns.demo3.CustomerDaoImpl.save())"/> -->
<!-- 环绕通知 -->
<aop:around method="around" pointcut="execution(public void com.alphajuns.demo3.CustomerDaoImpl.save())"/>
</aop:aspect>
</aop:config> </beans>
Spring框架中的AOP技术----配置文件方式的更多相关文章
- Spring框架中的AOP技术----注解方式
利用AOP技术注解的方式对功能进行增强 CustomerDao接口 package com.alphajuns.demo1; public interface CustomerDao { public ...
- spring框架中的aop技术
1. 什么是AOP, 面向切面编程 AOP为Aspect Oriented Programming的缩写, 意为:面向切面编程,主要是使各部分之间的耦合度降低, 提高程序的可重用性, 同时提高了开发的 ...
- 3.Spring框架中的标签与配置文件分离
1.Spring框架中标签的配置 1. id属性和name属性的区别 * id -- Bean起个名字,在约束中采用ID的约束,唯一 * 取值要求:必须以字母开始,可以使用字母.数字.连字符.下划线. ...
- Spring框架中的aop操作之二 通过配置文件实现增强
aop表达式写法 配置文件代码: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=&q ...
- Spring框架的Bean管理的配置文件方式
1. id属性和name属性的区别 * id -- Bean起个名字,在约束中采用ID的约束,唯一 * 取值要求:必须以字母开始,可以使用字母.数字.连字符.下划线.句话.冒号 id:不能出现特殊字符 ...
- Spring框架中的aop操作之一 及aspectjweaver.jar与aopalliance-1.0.jar下载地址 包含beans 注解context 和aop的约束
(aspect oriented programming面向切面编程) 首先在原有的jar包: 需Spring压缩包中的四个核心JAR包 beans .context.core 和expression ...
- Spring Security框架中踢人下线技术探索
1.背景 在某次项目的开发中,使用到了Spring Security权限框架进行后端权限开发的权限校验,底层集成Spring Session组件,非常方便的集成Redis进行分布式Session的会话 ...
- Spring框架的JDBC模板技术和事物
Spring框架的JDBC模板技术 技术分析之Spring框架的JDBC模板技术概述 1. Spring框架中提供了很多持久层的模板类来简化编程,使用模板类编写程序会变的简单 ...
- Spring框架IOC和AOP介绍
说明:本文部分内容参考其他优秀博客后结合自己实战例子改编如下 Spring框架是个轻量级的Java EE框架.所谓轻量级,是指不依赖于容器就能运行的.Struts.Hibernate也是轻量级的. 轻 ...
随机推荐
- XML Schema学习札记(1)——基础总览
内容整理自:www.w3school.com.cn 转载自:http://www.xgezhang.com/xml_schema_1.html 什么是XML Schema? XML Schema 是基 ...
- Hadoop系统通信协议介绍(转)
转载自 ---- http://weilaiyxj.iteye.com/blog/913166 本文约定: DN: DataNode TT: TaskTracker NN: NameNode SNN: ...
- 小强升职记(GTD)脑图
- Android面试常问到的知识点
一.算法,数据结构 1.排序算法 2.查找算法 3.二叉树 4.广度,深度算法: 二.java基础 1.集合Collection,List,Map等常用方法,特点,关系: 2.线程的同步,中断方式有几 ...
- 关于wcf,webservice,webapi或者其他服务或者接口有什么区别 WCF、WebAPI、WebService之间的区别 【转载】HTTP和SOAP完全就是两个不同的协议 WebService学习总结(一)——WebService的相关概念
wcf,webservice采用的是rpc协议,这个协议很复杂,所以每次要传递.要校验的内容也很复杂,别看我们用的很简单,但实际是frame帮我们做掉了rpc生成.解析的事情webapi遵循是rest ...
- python基础篇---实战---用户登入注册程序
一.首先了解需求: 1.支持多个用户登入 2.登入成功后显示欢迎,并退出程序 3.登入三次失败后,退出程序,并在下次程序启动尝试登入时,该用户名依然是锁定状态 二.文件代码如下: f = open(& ...
- sql between写法关于查时间区间是否重叠
--判断是否重叠 SELECT * FROM TABLEName WHERE starttime BETWEEN '2008-10-01' AND '2008-10-07' OR endtime BE ...
- myeclipse修改jsp文件的名称之后,再也打不开的解决方案
方案一.重启myEclipse 方案二. 删除对应workspace目录下 “.metadata\.plugins\org.eclipse.jst.jsp.core\jspsearch” 里的 *.i ...
- vim插件管理器的安装和配置-windows
# vim插件管理器的安装和配置-windows ### 前言------------------------------ vim做一框功能强大的编辑器,扩展功能令人称奇,插件机制非常灵活- 本篇推荐 ...
- The Definitive Guide To Django 2 学习笔记(二) 第二个View 动态内容
“Hello World”只是简单的展现了Django 基本的工作机制,但它不是动态的网页.第二个View我们将创建一个动态的网页,该页面上将展现当前的时间和日期. 该View需要做两件事,第一,计算 ...