Spring AOP是什么?你都拿它做什么?重庆时时历史开奖记录

原标题:Spring AOP是什么?你都拿它做什么?

<!-- 【环绕通知】 -->

<!-- dao实例加入容器 -->

3. 动态代理原理及实践

为了阐述清楚Spring AOP,我们从将以下方面进行讨论:

参考文章

}

* 2. 代理对象,要实现与目标对象一样的接口

}

System.out.println( "代理操作:提交事务...");

<!-- dao实例加入容器 -->

动态代理模式:动态代理类的源码是在程序运行期间,通过 JVM 反射等机制动态生成。代理类和委托类的关系是运行时才确定的。实例如下:

<aop:aspectref="transactionAop">

责任编辑:

// 返回对目标对象(target)代理后的对象(proxy)

publicObject getProxyInstance(){

Object proxy = Proxy.newProxyInstance(

<aop:config>

<beanid="orderDao"class="test.spring_aop_anno.OrderDao"></bean>

publicvoidfind(){

System.out.println( "模拟:查询用户");

//目标对象

classUserDaoimplementsIUserDao{

newInvocationHandler() { // 执行代理对象方法时候触发

publicObject invoke(Object proxy, Method method, Object[] args)

throwsThrowable {

http://www.springframework.org/schema/beans/spring-beans.xsd

* 2. 目标对象必须要实现接口

转自:我叫刘半仙,

切入点表达式不在这里介绍。参考 Spring AOP 切入点表达式

target.getClass().getClassLoader(), // 目标对象使用的类加载器

CGLIB 是以动态生成的子类继承目标的方式实现,在运行期动态的在内存中构建一彩票双色球开奖个子类,如下:

// 接收一个目标对象

privateObject target;

publicProxyFactory(Object target){

this.target = target;

// 方法返回值

Object result = null;

到这里,我们已经全部介绍完Spring AOP。回到开篇的问题,我们拿它做什么?

publicvoidfind(){

System.out.println( "查询");

https://my.oschina.net/liughDevelop/blog/1457097

}

}

*

<?xml version="1.0"encoding="UTF-8"?>

}

*/

//目标对象

classUserDaoimplementsIUserDao{

}

<!-- 【后置通知】 -->

<!-- 异常通知 -->

http://www.springframework.org/schema/context

voidfind();

@Override

}

publicvoidafterReturing(){

System.out.println( "[返回后通知]");

pjp.proceed(); // 执行目标方法

System.out.println( "[环绕后:]");

2. 静态代理原理及实践

Spring 的 XML 配置文件:

publicvoidsave(){

System.out.println( "模拟: 保存用户!");

知道了原理,现在我们将自己手动实现 Spring 的 AOP:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

静态代理模式:静态代理说白了,就是在程序运行前就已经存在代理类的字节码文件、代理类和原始类的关系在运行前就已经确定。废话不多说,我们看一下代码。为了方便阅读,博主把单独的 class 文件合并到接口中,读者可以直接复制代码运行:

// 执行目标对象方法

result = method.invoke(target, args);

}

}

<!-- 【返回后通知】 -->

@Override

packagetest.staticProxy;

// 接口

publicinterfaceIUserDao{

voidsave();

http://www.springframework.org/schema/aop

为什么会有面向切面编程(AOP)?我们知道Java是一个面向对象(OOP)的语言,但它有一些弊端,比如当我们需要为多个不具有继承关系的对象引入一个公共行为,例如日志、权限验证、事务等功能时,只能在在每个对象里引用公共行为。这样做不便于维护,而且有大量重复代码。AOP的出现弥补了OOP的这点不足。

// 获取当前执行的澳客方法的方法名

String methodName = method.getName();

http://www.springframework.org/schema/aop/spring-aop.xsd">

returnresult;

returnproxy;

代码的测试结果如下:

// 用于测试 CGLIB 动态代理

classOrderDao{

}

}

博主一个人的力量有限,只能列举这么多,欢迎评论区对文章做补充。

}

//用于测试 JDK 动态代理

classUserDaoimplementsIUserDao{

//切面类

classTransactionAop{

<!-- 切入点表达式定义 -->

@Override

<aop:beforemethod="beginTransaction"pointcut-ref="transactionPointcut"/>

<!-- 切面配置 -->

http://www.springframework.org/schema/beans

现在,我们可以看看 AOP 的定义:面向切面编程,核心原理是使用动态代理模式在方法执行前后或出现异常时加入相关逻辑

<!-- 【前置通知】 在目标方法之前执行 -->

简单的从字面意思看出:如果有接口,则使用 JDK 代理,反之使用 CGLIB ,这刚好印证了前文所阐述的内容。Spring AOP 综合两种代理方式的使用前提有会如下结论:如果目标类没有实现接口,且 class 为 final 修饰的,则不能进行 Spring AOP 编程!

}

classProxyFactory{

}

}

<beanid="transactionAop"class="test.spring_aop_anno.TransactionAop"></bean>

voidfind();

/**

* 动态代理:

publicvoidsave(){

//int i =1/0; 用于测试异常通知

System.out.println( "保存订单...");

前文提到 JDK 代理和 CGLIB 代理两种动态代理。优秀的 Spring 框架把两种方式在底层都集成了进去,我们无需担心自己去实现动态生成代理。那么,Spring是如何生成代理对象的?

publicvoidafterThrowing(){

System.out.println( "[异常通知]");

importjava.lang.reflect.Method;

target.getClass().getInterfaces(), // 目标对象实现的所有接口

@Override

publicvoidsave(){

System.out.println( "代理操作: 开启事务...");

通过定义和前面代码我们可以发现3点:

4. Spring AOP

publicvoidbeginTransaction(){

System.out.println( "[前置通知] 开启事务..");

CGLIB 使用的前提是目标类不能为 final 修饰。因为 final 修饰的类不能被继承。

</aop:aspect>

<!-- 实例化切面类 -->

}

// 代理对象,需要维护一个目标对象

privateIUserDao target = newUserDao();

@Override

// 直接调用目标对象方法

result = method.invoke(target, args);

}

publicvoidarroud(ProceedingJoinPoint pjp)throwsThrowable {

System.out.println( "[环绕前:]");

}

/**

* 静态代理

xmlns:aop="http://www.springframework.org/schema/aop"

System.out.println( "开启事务...");

测试结果:

使用 JDK 生成的动态代理的前提是目标类必须有实现的接口。但这里又引入一个问题,如果某个类没有实现接口,就不能使用 JDK 动态代理。所以 CGLIB 代理就是解决这个问题的。

其实是 JDK 动态生成了一个类去实现接口,隐藏了这个过程:

<aop:aroundmethod="arroud"pointcut-ref="transactionPointcut"/>

packagetest.spring_aop_anno;

importorg.aspectj.lang.ProceedingJoinPoint;

<aop:after-throwingmethod="afterThrowing"pointcut-ref="transactionPointcut"/>

xmlns:context="http://www.springframework.org/schema/context"

classUserDaoProxyimplementsIUserDao{

}

代理模式:为其他对象提供一种代理以控制对这个对象的访问。这段话比较官方,但我更倾向于用自己的语言理解:比如A对象要做一件事情,在没有代理前,自己来做;在对 A 代理后,由 A 的代理类 B 来做。代理其实是在原实例前后加了一层处理,这也是 AOP 的初级轮廓。

<beanid="userDao"class="test.spring_aop_anno.UserDao"></bean>

importjava.lang.reflect.Proxy;

}

publicvoidfind(){

target.find();

packagetest.dynamicProxy;

importjava.lang.reflect.InvocationHandler;

<aop:aftermethod="commit"pointcut-ref="transactionPointcut"/>

xsi:schemaLocation="

}

*/

}

}

}

if( "find".equals(methodName)) {

<aop:after-returningmethod="afterReturing"pointcut-ref="transactionPointcut"/>

}

<beansxmlns="http://www.springframework.org/schema/beans"

<!-- Aop相关配置 -->

<aop:pointcutexpression="execution(* test.spring_aop_anno.*Dao.*(..))"id="transactionPointcut"/>

静态代理虽然保证了业务类只需关注逻辑本身,代理对象的一个接口只服务于一种类型的对象。如果要代理的方法很多,势必要为每一种方法都进行代理。再者,如果增加一个方法,除了实现类需要实现这个方法外,所有的代理类也要实现此方法。增加了代码的维护成本。那么要如何解决呢?答案是使用动态代理。

}

publicinterfaceIUserDao{

voidsave();

@Override

</beans>

// 接口

publicinterfaceIUserDao{

voidsave();

publicvoidsave(){

System.out.println( "模拟:保存用户!");

@Override

target.save(); // 执行目标对象的方法

Spring AOP还能做什么,实现什么魔幻功能,就在于我们每一个平凡而又睿智的程序猿!

}

* 代理工厂,给多个目标对象生成代理对象!

publicvoidsave(){

//int i =1/0; 用于测试异常通知

System.out.println( "保存用户...");

IUserDao proxy = (IUserDao) newProxyFactory(target).getProxyInstance();

} else{

);

测试结果如下:

</aop:config>

* 特点:

System.out.println( "提交事务...");

1. 代理模式

class$jdkProxyimplementsIUserDao{}

publicvoidcommit(){

System.out.println( "[后置通知] 提交事务..");

}

http://www.springframework.org/schema/context/spring-context.xsd

本文地址:http://mbq8.com/post/164.html 转载请注明出处!