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也是轻量级的. 轻 ...
随机推荐
- Android实战技巧之三十八:Handler使用中可能引发的内存泄漏
问题描写叙述 曾几何时,我们用原来的办法使用Handler时会有以下一段温馨的提示: This Handler class should be static or leaks might occur ...
- Java中abstract class 和 interface 的解释和他们的异同点(转)
(一)概述 在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制.正是由于这两种机制的存 在,才赋予了Java强大的 面向对象能力.abstract ...
- 如何监控MYSQL消耗服务器资源
http://258xiaolei-sina-com.iteye.com/blog/764665 启动Mysql时加参数--log-slow-queries来记录执行时间超过long_query_ti ...
- CSRF攻击原理及测试方法
CSRF(Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,该攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在并未授权的情况下执 ...
- 异常:Caused by: java.lang.NoSuchMethodError: javax.persistence.OneToMany.orphanRemoval()Z/Caused by: java.lang.NoSuchMethodError: javax.persistence.JoinColumn.foreign
Spring3.0 + Hibernate3.5:启动服务器报:Caused by: java.lang.NoSuchMethodError: javax.persistence.OneToMany. ...
- Ubuntu下开启mysql远程登陆权限
在腾讯云上租了个云服务器,并且安装启动了mysql. 这时候用本地的mysql workbench去连接就会报错,提示无法成功连接. 其实这是因为没有开启账户的远程登陆权限.那么下面就开启一下: 1. ...
- C# Oracle.ManagedDataAccess 批量更新表数据
这是我第一次发表博客.以前经常到博客园查找相关技术和代码,今天在写一段小程序时出现了问题, 但在网上没能找到理想的解决方法.故注册了博客园,想与新手分享(因为本人也不是什么高手). vb.net和C# ...
- 工作总结 .ToString("000000")
; ");//000123 指定格式 Console.WriteLine(ssp); ; ");//123456789 超过了返回原值 Console.WriteLine(ss);
- delete与delete [] 真正差别
我们通常从教科书上看到这种说明: delete 释放new分配的单个对象指针指向的内存 delete[] 释放new分配的对象数组指针指向的内存 那么,依照教科书的理解,我们看下以下的代码: int ...
- NOIP2007:纪念品分组
#include<stdio.h> #include<stdlib.h> int a[100]; int main(){ int i,j,k,m,n,w; scanf(&quo ...