spring AOP面向切面编程学习笔记
一、面向切面编程简介:

在调用某些类的方法时,要在方法执行前或后进行预处理或后处理;预处理或后处理的操作被封装在另一个类中。如图中,UserService类在执行addUser()或updateUser方法前开启事务,执行完后要提交事务;而几乎所有数据库操作都是如此,那么就可以将事务操作的方法提取出封装到一个类里。然后再利用代理类进行处理(目标类方法增强),返回代理类对象
二、AOP相关术语
Target:目标类,需要被增强的类。
JoinPoint:连接点,目标类上需要被增强的方法。(这些方法可以被增强,也可能不增强)。
PointCut:切入点,被增强的连接点(已经增强了)。切入点术语特殊的连接点
Advice:增强/通知,增强的方法。
weaving:织入,将切入点和通知结合,生成代理类过程。
Proxy:代理类。
Aspect:切面,切入点和通知结合形成的面

三、JDK动态代理模拟AOP

1、项目结构(接口+目标类+切面类+代理类+测试类)

2、新建接口UserService
package hjp.springAOP.jdkProxy;
public interface UserService {
void addUser();
void updateUser();
}
UserService
3、新建目标类UserServiceImpl,并实现接口UserService
package hjp.springAOP.jdkProxy;
public class UserServiceImpl implements UserService {
@Override
public void addUser() {
// TODO Auto-generated method stub
System.out.println("jdk add user");
}
@Override
public void updateUser() {
// TODO Auto-generated method stub
System.out.println("jdk update user");
}
}
UserServiceImpl
4、新建切面类MyAspect
package hjp.springAOP.jdkProxy; /**
* 切面类,用于存放增强
*
* @author JiaPeng
*
*/
public class MyAspect {
public void beafore() {
System.out.println("before");
} public void after() {
System.out.println("after");
}
}
MyAspect
5、新建代理类MyFactory
package hjp.springAOP.jdkProxy; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /**
* 工厂生成代理类,目的:将目标类(切入点)和切面类(通知)结合。
*
* @author JiaPeng
*
*/
public class MyFactory {
public static UserService createService() {
// 创建目标类
final UserService userService = new UserServiceImpl();
// 创建切面类
final MyAspect myAspect = new MyAspect();
// 使用jdk动态代理,生成代理类
// 第一个参数是,当前类下的类加载器,第二个参数是目标类所继承的接口数组,第三个参数是匿名内部类
// 匿名内部类也就是没有名字的内部类;正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写;但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
UserService proxyService = (UserService) Proxy.newProxyInstance(MyFactory.class.getClassLoader(),
userService.getClass().getInterfaces(), new InvocationHandler() {
// 代理类每一个方法执行时,都将调用处理类的invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
// 执行前通知
myAspect.beafore();
// 执行目标类的相应方法
Object obj = method.invoke(userService, args);
// 执行后通知
myAspect.after();
return obj;
}
});
return proxyService;
}
}
代理类
6、新建测试类
package hjp.springAOP.jdkProxy;
import org.junit.Test;
public class TestApp {
@Test
public void demo1() {
UserService userService = MyFactory.createService();
userService.addUser();
userService.updateUser();
}
}
测试类
四、CGLIB模拟AOP
cglib 字节码增强工具,一般框架都使用。只要有类就可以增强
1、项目结构(cglib的jar包已被spring打包好了,所以添加了spring的主要jar包就可以了)

2、新建目标类UserServiceImpl,没有接口
package hjp.springAOP.cglibProxy;
public class UserServiceImpl {
public void addUser() {
System.out.println("cglib add user");
}
public void updateUser() {
System.out.println("cglib update user");
}
}
UserServiceImpl
3、新建切面类
package hjp.springAOP.cglibProxy; /**
* 切面类,用于存放增强
*
* @author JiaPeng
*
*/
public class MyAspect {
public void beafore() {
System.out.println("before");
} public void after() {
System.out.println("after");
}
}
切面类
4、新建代理类
package hjp.springAOP.cglibProxy; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import org.eclipse.jdt.internal.compiler.classfmt.FieldInfoWithAnnotation;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; /**
* 工厂生成代理类,目的:将目标类(切入点)和切面类(通知)结合。
*
* @author JiaPeng
*
*/
public class MyFactory {
public static UserServiceImpl createService() {
// 创建目标类
final UserServiceImpl userServiceImpl = new UserServiceImpl();
// 创建切面类
final MyAspect myAspect = new MyAspect();
// 使用cglib创建代理类,其实现方式就是在cglib运行时,动态创建目标类子类(该子类就是代理类,Java动态代理是基于接口或父类的)
// 创建核心类
Enhancer enhancer = new Enhancer();
// 设置父类
enhancer.setSuperclass(userServiceImpl.getClass());
// 代理类方法将调用回调函数,等效JDK InvocationHandler
// 接口Callback,子接口MethodInterceptor对方法进行增强
enhancer.setCallback(new MethodInterceptor() { @Override
// 前三个参数与jdk动态代理invoke相同
// 第四个参数是方法代理
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
throws Throwable {
// TODO Auto-generated method stub
// 切面类的前通知
myAspect.beafore();
// 目标方法
//Object object = method.invoke(userServiceImpl, args);
Object object = methodProxy.invokeSuper(proxy, args);//执行代理类(子类)父类方法(父类就是目标类),效果和上面的一样
// 切面类后通知
myAspect.after();
return object;
}
});
// 创建代理类
return (UserServiceImpl) enhancer.create();
}
}
代理类
5、新建测试类
package hjp.springAOP.cglibProxy;
import org.junit.Test;
public class TestApp {
@Test
public void demo1() {
UserServiceImpl userService = MyFactory.createService();
userService.addUser();
userService.updateUser();
}
}
测试类
五、利用spring工厂bean,半自动化模拟AOP
使用spring提供FactoryBean创建代理对象,手动的获取代理对象。生成代理需要应用增强(通知),通知需要确定方法名称。spring规范规定通知类型从而确定方法名称。
AOP联盟五种通知类型,spring对AOP联盟进行支持。
前置通知:org.springframework.aop.MethodBeforeAdvice 在目标方法执行前实施增强
后置通知:org.springframework.aop.AfterReturningAdvice 在目标方法执行后实施增强
环绕通知:org.aopalliance.intercept.MethodInterceptor 在目标方法执行前后实施增强
异常抛出通知:org.springframework.aop.ThrowsAdvice 在方法抛出异常后实施增强
引介通知:org.springframework.aop.Introductioninterceptor 在目标类中添加一些新的方法和属性
环绕通知可以模拟其他通知类型,如:
try{
前置
//必须手动执行目标方法
后置
}catch{
//异常抛出
}
1、项目结构:(新加AOP联盟的jar包和spring对AOP依赖的jar包)

2、接口UserService及其实现类UserServiceImpl同上面一样
3、切面类MyAspect不一样了,需要继承接口MethodInterceptor并实现其方法,代码如下:
package hjp.springAOP.springFactoryBeanProxy; import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; /**
* 切面类,用于存放通知(增强),使用的AOP联盟规范,必须实现接口,从而确定方法名称(即,spring如何执行通知)
*
* @author JiaPeng
*
*/
public class MyAspect implements MethodInterceptor { @Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
// TODO Auto-generated method stub
System.out.println("前");
//环绕通知,必须手动的执行目标方法
Object obj=methodInvocation.proceed(); System.out.println("后");
return obj;
} }
切面类
4、测试类代码如下:
package hjp.springAOP.springFactoryBeanProxy; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestApp {
@Test
public void demo1() {
String xmlPath="hjp/springAOP/springFactoryBeanProxy/beans.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);
UserService userService = (UserService)applicationContext.getBean("proxyServiceId");
userService.addUser();
userService.updateUser();
}
}
测试类
5、新建beans.xml配置文件,里面有注解,不再赘述,注意配置中可以设置是否使用cglib代理
<?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">
<!-- 1、创建目标类 -->
<bean id="userServiceId" class="hjp.springAOP.springFactoryBeanProxy.UserServiceImpl"></bean>
<!-- 2、创建切面类 (通知) -->
<bean id="myAspectId" class="hjp.springAOP.springFactoryBeanProxy.MyAspect"></bean>
<!-- 3、生成代理,将目标类与切面类结合 ProxyFactoryBean:生成一个特殊代理Bean -->
<bean id="proxyServiceId" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 确定接口 -->
<property name="interfaces"
value="hjp.springAOP.springFactoryBeanProxy.UserService"></property>
<!-- 确定目标类 -->
<property name="target" ref="userServiceId"></property>
<!-- 确定通知,使用切面类名称 -->
<property name="interceptorNames" value="myAspectId"></property>
<!-- 强制使用cglib代理,如果不使用cglib可以不写,默认为false -->
<property name="optimize" value="true"></property>
</bean>
</beans>
配置文件
六、传统springAOP
1、项目结构(较上面中的引用,新增了aspectj的jar包)

2、接口UserService及其实现类UserServiceImpl如上,MyAspect切面类也是如上实现接口MethodInterceptor
3、beans.xml配置文件,注意要加xsd引用(命名空间xmlns:aop="http://www.springframework.org/schema/aop;引用地址:http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd)
<?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">
<!-- 1、创建目标类 -->
<bean id="userServiceId" class="hjp.springAOP.springAOP.UserServiceImpl"></bean>
<!-- 2、创建切面类 (通知) -->
<bean id="myAspectId" class="hjp.springAOP.springAOP.MyAspect"></bean>
<!-- spring 传统AOP开发,使通知引用到目标类切入点上 -->
<aop:config>
<!-- pointcut用于声明切入点,确定目标类上哪些方法将被增强 expression用于编写切入点表达式,(aspectj 切入点表达式)
固定格式:execution(* hjp.springAOP.springAOP.*.*(..)) 第一个* 表示返回值类型,接着是包名称,第二个*
是类名,第三个是方法名,后面括号内点点是参数列表 -->
<aop:pointcut expression="execution(* hjp.springAOP.springAOP.*.*(..))"
id="myPointCut" />
<!-- advice-ref:通知引用;pointcut-ref:切入点引用 -->
<aop:advisor advice-ref="myAspectId" pointcut-ref="myPointCut" />
</aop:config>
</beans>
配置文件
4、测试类代码:
package hjp.springAOP.springAOP; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestApp {
@Test
public void demo1() {
String xmlPath="hjp/springAOP/springAOP/beans.xml";
ApplicationContext applicationContext=new ClassPathXmlApplicationContext(xmlPath);
UserService userService = (UserService)applicationContext.getBean("userServiceId");
userService.addUser();
userService.updateUser();
}
}
测试类
spring AOP面向切面编程学习笔记的更多相关文章
- 详细解读 Spring AOP 面向切面编程(二)
本文是<详细解读 Spring AOP 面向切面编程(一)>的续集. 在上篇中,我们从写死代码,到使用代理:从编程式 Spring AOP 到声明式 Spring AOP.一切都朝着简单实 ...
- 浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~
简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring ...
- 从源码入手,一文带你读懂Spring AOP面向切面编程
之前<零基础带你看Spring源码--IOC控制反转>详细讲了Spring容器的初始化和加载的原理,后面<你真的完全了解Java动态代理吗?看这篇就够了>介绍了下JDK的动态代 ...
- 【Spring系列】Spring AOP面向切面编程
前言 接上一篇文章,在上午中使用了切面做防重复控制,本文着重介绍切面AOP. 在开发中,有一些功能行为是通用的,比如.日志管理.安全和事务,它们有一个共同点就是分布于应用中的多处,这种功能被称为横切关 ...
- Spring AOP面向切面编程详解
前言 AOP即面向切面编程,是一种编程思想,OOP的延续.在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等等.在阅读本文前希望您已经对Spring有一定的了解 注:在能对代码进行添 ...
- Spring AOP 面向切面编程相关注解
Aspect Oriented Programming 面向切面编程 在Spring中使用这些面向切面相关的注解可以结合使用aspectJ,aspectJ是专门搞动态代理技术的,所以比较专业. ...
- Spring AOP 面向切面编程入门
什么是AOP AOP(Aspect Oriented Programming),即面向切面编程.众所周知,OOP(面向对象编程)通过的是继承.封装和多态等概念来建立一种对象层次结构,用于模拟公共行为的 ...
- 详细解读 Spring AOP 面向切面编程(一)
又是一个周末, 今天我要和大家分享的是 AOP(Aspect-Oriented Programming)这个东西,名字与 OOP 仅差一个字母,其实它是对 OOP 编程方式的一种补充,并非是取而代之. ...
- Spring Aop面向切面编程&&自动注入
1.面向切面编程 在程序原有纵向执行流程中,针对某一个或某一些方法添加通知,形成横切面的过程叫做面向切面编程 2.常用概念 原有功能:切点,pointcut 前置通知:在切点之前执行的功能,befor ...
随机推荐
- 解析 HTTP(HttpURLConnection getResponseCode)
HTTP 请求 客户端通过发送 HTTP 请求向服务器请求对资源的访问.HTTP 请求由三部分组成,分别是:请求行.消息报头和请求征文. 3.1.请求行 请求行以一个方法符号开头,后面跟着请求 URI ...
- usb驱动开发2之代码地图
USB只是Linux庞大家族里的一个小部落,host controller是它们的族长,族里的每个USB设备都需要被系统识别.下图显示包含一个USB接口的USB鼠标导出的结果. USB系统中的第一个U ...
- android camera setParameters failed 类问题分析总结
在 monkey test 测试中出现了一例 RuntimeException ,即 setParameters failed. LOG显示为:09-01 18:47:17.348 15656 156 ...
- 加密算法使用(四):AES的使用
AES是一种对称加密方式,比DES更为安全,用一个秘钥加密数据之后,可以用同一个秘钥对加密后的数据解密还原,以下是一套以字符串为例子的使用全过程演示, 用到了 commons-codec.jar pa ...
- Caffe学习系列(17):模型各层数据和参数可视化
cifar10的各层数据和参数可视化 .caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1p ...
- 从0开始学Java——@override的作用
早上跟着<jsp&Servlet学习笔记>来学习jsp,在使用eclipse创建了一个servlet类之后,发现自动创建的类和书上相比,doGet方法的前面少了@override, ...
- tabbar的自定义
[self createCustomTabBar]; -(void)createCustomTabBar{ //创建一个UIImageView,作为底图 UIImageView *bgVi ...
- 一个基于.NET平台的自动化/压力测试系统设计简述
AutoTest系统设计概述 AutoTest是一个基于.NET平台实现的自动化/压力测试的系统,可独立运行于windows平台下,支持分布式部署,不需要其他配置或编译器的支持.(本质是一个基于协议的 ...
- Jquery.validate.js表单验证插件的使用
作为一个网站web开发人员,以前居然不知道还有表单验证这样好呀的插件,还在一行行写表单验证,真是后悔没能早点知道他们的存在. 最近公司不忙,自己学习一些东西的时候,发现了validation的一个实例 ...
- 扫描二维码下载安装apk的app
将apk文件放到服务器上,下载链接直接生成二维码,用微信扫描时不能直接下载.页面只是刷新一下. 想实现微信扫描下载apk的app客户端,需要把下载链接做到一个网页上, 将网页生成一个二维码. 直接下载 ...