spring aop是将系统中业务横切逻辑通过动态代理技术jdk动态代理或者cglib方式织入到指定类指定方法的指定位置上去。
所以springaop其实就是对jdk动态代理和cglib字节码生成技术的一种封装。
连接点:针对一个方法 方法调用前 还是调用后 还是异常抛出后 。。
切点:哪些类的哪些方法
增强:横切逻辑
切面:连接点+增强+切点
如果需要spring生成代理类 那么就需要提供切面信息,或者提供增强,连接点 目标对象。
封装点一advice:
spring中各种增强接口:其实已经包含了连接点的信息了。
org.springframework.aop.BeforeAdvice
org.springframework.aop.AfterReturningAdvice
org.aopalliance.intercept.MethodInterceptor
org.springframework.aop.ThrowsAdvice
ThrowsAdvice的设计比较特别。ThrowsAdvice是标致接口 什么都没有其实什么都有了
规定 方法名afterThrowing
前三个参数 Method method,Object[] args,Object[] target 要么都有要么没有
Throwable 或者其子类
这样异常抛出的时候 spring就会自动去匹配调用哪个方法了,有点模仿try cache设计
怎么自动匹配的呢:
最简单就是通过反射获取各个方法异常类型,这样就能确定调用哪个方法了。
还有就是在生成代理对象时候维护个列表信息,这种方法可能性比较大。
封装点二advisor:提供方便的切点配置
spring提供的切面接口:切面很重要 因为切面包含了连接点+增强+切点所以你如果有了切面的信息那么就能通过spring代理工厂产生代理对象。
1.StaticMethodMatcherPointcutAdvisor 匹配静态方法
2.RegexpmethodpointAdvisor 用正则表达式匹配
3.DynamicMethodMatcherPointcut 和 DefaultPointcutAdvisor 动态方法意思就是不光具有静态方法匹配 还能进行实际运行时候的值匹配。 运行时候判断实际参数DefaultPointcutAdvisor 里面包含DynamicMethodMatcherPointcut 和advice 这样进行配置 首先会根据静态切点生成代理类 ,具体是否需要加入增强逻辑在允许时候判断动态切点匹配方法是否能匹配上(真实的参数进行判断才能决定是否需要增强 效率低下)。
4.ControlFlowPointCut 和 DefaultPointcutAdvisor 允许时候判断方法堆栈信息。 同上
5.ComposablePointCut 和 DefaultPointcutAdvisor 同上 定义多个PointCut可以取交集
生成代理的方式发展
ProxyFactory->ProxyFactoryBean->BeanNameAutoProxyCreator->DefaultAdvisorAutoProxyCreator->AnnotationAwareAspectJAutoProxyCreator(注解方式)
ProxyFactory 增强接口实现类 或者直接提供切面接口实现类 必须提供目标对象 。
ProxyFactoryBean 同上 只是这里使用了工厂bean配置文件的方式。 这两种方式很麻烦必须提供目标对象才能获取代理对象。
BeanNameAutoProxyCreator
DefaultAdvisorAutoProxyCreator
比如你配置了<bean id="waiterTarget" class="com.baobaotao.advisor.Waiter" /> 还有切面对象 和 DefaultAdvisorAutoProxyCreator
getBean取到的就已经是代理对象了,spring会在bean生命周期BeanPostProcessor里面作相关的处理 。
配置一个Advisor已经包含了切点和增强的信息spring是可以知道哪些需要创建代理对象的,
BeanPostProcessor会干预所有的容器中的bean且能够拦截到bean实例化前实例化后的处理。这样创建代理bean就有可能发生了。
同样:
类同于ProxyFactory 用法的有AspectProxyFactory 类 设置个目标对象添加切面就可以生成代理对象了。
AnnotationAwareAspectJAutoProxyCreator(注解方式) 注解扫描 <aop:aspectj-autoproxy />更加简化 基于注解的切面扫描 引入基于Schema的aop命名空间进行配置 属性proxy-target-class 为false
============================细节======================
jdk动态代理和cglib比对
查看jdk动态代理源码可以看到:获取所有的接口然后通过接口的方法属性生成代理类 在获取代理类的构造函数通过反射的方式创建对象,在代理对象中存在目标对象 每次对目标对象的调用都是通过反射进行调用的。
cglib通过生成子类的方式来实现代理的,所以不能对finally private方法进行代理。 这样cglib生成了子类直接构造子类的实例句柄。执行时候效率高 生成代理类时间长。
总结:jdk方式创建代理对象快 执行对象方法慢
cglib方式创建代理对象慢 执行对象方法快
创建代理对象jdk快10倍左右。
执行cglib快10倍左右。
这样的特点如果是单例 或者对象池化了 那么使用cglib很划算
如果不是单例 那么使用jdk方式比较划算。
spring ProxyFactory 对jdk和gblib进行了封装。
ProxyFactoryBean几个属性有必要了解下:
interfaces/proxyInterfaces 代理需要实现的接口,可以是多个或者一个
interceptorNames 就是那些增强
singleton 是否单例
optimize 设置为true使用cglib 如果单例最好使用cglib 其他作用域最好使用jdk动态代理
proxyTargetClass 设置填true表示使用cglib 前面的设置存在优先级关系。有了这个忽视了前面设置的接口。
<!-- 普通方法名匹配切面其他4个类同 -->
<bean id="waiterTarget" class="com.baobaotao.advisor.Waiter" />
<bean id="sellerTarget" class="com.baobaotao.advisor.Seller" />
<bean id="greetingAdvice" class="com.baobaotao.advisor.GreetingBeforeAdvice" />
<bean id="greetingAdvisor" class="com.baobaotao.advisor.GreetingAdvisor"
p:advice-ref="greetingAdvice" />
<bean id="parent" abstract="true"
class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="greetingAdvisor" p:proxyTargetClass="true" />
<bean id="waiter" parent="parent" p:target-ref="waiterTarget" />
<bean id="seller" parent="parent" p:target-ref="sellerTarget" />
public class GreetingAdvisor extends StaticMethodMatcherPointcutAdvisor {
public boolean matches(Method method, Class clazz) {
return "greetTo".equals(method.getName());
}
public ClassFilter getClassFilter(){
return new ClassFilter(){
public boolean matches(Class clazz){
return Waiter.class.isAssignableFrom(clazz);
}
};
}
}
public class GreetingBeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object obj) throws Throwable {
String clientName = (String)args[0];
System.out.println(obj.getClass().getName()+"."+method.getName());
System.out.println("How are you!Mr."+clientName+".");
}
}
总结:以上代码是通过ProxyFactoryBean方式获取代理对象其实和DefaultAdvisorAutoProxyCreator大同小异
如果通过spring容器获取一个bean 首先ProxyFactoryBean获取者DefaultAdvisorAutoProxyCreator会查找到你是否配置了advisor如果配置了 查看这个classfilter 是否存在这样的类 如果有 查找methodMatcher
看是否存在匹配的方法 如果有根据advisor里面配置的advice获取到增强 生成代理对象返回给客户端,这就是代理对象的生成过程。
ProxyFactoryBean将逻辑放在工厂方法里面。
DefaultAdvisorAutoProxyCreator放到后处理bean里面。
还有
基于@AspectJ注解方式 <aop:aspectj-autoproxy />这个可以简洁扫描。
基于Schama配置切面如果不能使用jdk5那么就使用这种配置方式了。
eg:
<aop:config>
<aop:aspect ref="">
<aop:before pointcut="" method=""/>//这里只要一个类就行 指定方法名
</aop:aspect >
</aop:config>
或者
<aop:config>
<aop:advisor advice-ref="" pointcut=""/> //这里的advice需要实现增强接口
</aop:config>
可以参考spring3.x企业应用开发实战一书第七章 很详细
原理是一样 用法不一样 所以他们可以混用。
补充:同一对象内的嵌套方法调用拦截失败问题。
无论spring使用的jdk动态代理或者cglib对目标对象进行代理,最后方法调用肯定是在目标对象上的而不是代理对象。
public class TestClass{
public void testMethod1(){
};
public void testMethod2(){
testMethod1();
};
}
如果TestClass testMethod1 testMethod2 两个方法都被aop进行了代理那么在代理对象调用方法testMethod2()时候testMethod2方法确实被代理了 但是testMethod1却没有被代理 ,
原因 调用testMethod1其实发生在目标对象的内部并不是在代理对象上,所以如果一定要调用代理后的testMethod1可以这样:((TestClass)AopContext.currentProxy().testMethod1();
这样就没有问题了currentProxy()这个方法也是从Threadlocal中获取到的当前代理对象,由spring进行维护的。
相关推荐
本篇文章将深入探讨如何使用Spring的动态代理机制实现AOP,以及XML配置的相关知识。 一、面向切面编程(AOP) AOP的核心概念是切面(Aspect)、连接点(Join Point)、通知(Advice)、切入点(Pointcut)和织入...
Spring AOP可以利用JDK动态代理来实现对方法的拦截,当调用目标对象的方法时,实际上执行的是代理对象的方法,从而实现在方法执行前后加入额外逻辑。 以下是使用JDK动态代理实现Spring AOP的步骤: 1. **定义切面...
本篇文章将深入探讨如何利用Spring的注解来实现AOP,以及其背后的动态代理机制。 首先,了解AOP的基本概念是必要的。AOP的核心是切面(Aspect),它封装了跨越多个对象的行为或关注点。切点(Join Point)是程序...
1. **JDK动态代理**:当我们的代理对象是由Spring的JdkDynamicAopProxy创建时,`AopTargetUtils`可以剥离掉代理对象,暴露底层的Java接口实现。 2. **CGLIB代理**:如果目标对象被CGLIB库动态增强,`AopTargetUtils...
2.cglib封装了asm,可以在运行期动态生成新的class。 3.cglib用于AOP,jdk中的proxy必须基于接口,cglib却没有这个限制。 spring 的AOP功能中 会根据目标类是否实现了接口来判断使用 jdk Proxy还是cglib
* 动态代理升级类测试 * @author FANGJINXIN * */ public class ProxyUpTest { public static void main(String[] args) { UserMgr userMgr = new UserMgrImpl(); Object proxy = ProxyUp.newProxy...
基于代理的AOP主要使用了我们前面提到的动态代理,它可以对基于接口的类进行代理,而CGLIB库则用于那些没有接口或者需要更底层代理的情况。 Spring AOP中的切面(Aspect)是一个封装了多个相关通知(Advice,即切面...
在Java 1.8环境下,Spring AOP支持两种类型的代理:JDK动态代理和CGLIB代理。JDK动态代理适用于实现了接口的类,而CGLIB代理则适用于没有实现接口的类。在本项目中,可能使用了JDK动态代理,因为描述中提到了"需要...
- **提供工厂方法**:根据配置信息动态创建`HttpInvokerProxyFactoryBean`实例,并返回代理对象。 - **异常处理**:封装异常处理逻辑,比如统一的错误码、错误信息等。 - **超时设置**:根据业务需求设置请求超时...
【Spring AOP的静态代理和动态代理】 在软件开发中,代理模式是一种常见的设计模式,它允许我们在不修改原有对象的基础上,对对象的行为进行增强。代理模式的核心思想是通过代理对象来控制对原始对象(也称为委托...
本篇将详细探讨JDK动态代理和Spring AOP,以及它们在实际应用中的作用。 首先,JDK动态代理是Java提供的一种在运行时创建代理对象的技术。它允许我们在不修改原有类的基础上,为已有接口添加额外的功能。动态代理的...
Spring支持两种代理机制:基于接口的JDK动态代理和基于类的CGLIB代理。 CGLIB(Code Generation Library)是一个强大的高性能代码生成库,其底层是通过使用操作Java字节码的开源字节码操作框架(比如ASM)来实现的...
在Spring中,AOP代理有两种实现方式:JDK动态代理和CGLIB代理。JDK代理适用于实现了接口的类,而CGLIB代理则适用于未实现接口的类。 1. **JDK动态代理**: - Spring通过实现`java.lang.reflect.InvocationHandler`...
在本示例中,我们将深入探讨如何利用Spring框架与JDBC的整合来实现转账业务,并通过动态代理模式来优化事务管理。动态代理模式是Java中一种强大的设计模式,它允许我们在运行时创建对象的代理,以拦截方法调用并执行...
Spring提供了两种AOP代理方式:JDK动态代理和CGLIB。如果目标对象实现了至少一个接口,Spring会选择JDK动态代理;如果没有实现接口,Spring则会使用CGLIB代理。 AOP在Spring中的实现还涉及了切点(Pointcut)、通知...
“006_Dynamic_Proxy_Spring_AOP”文件很可能是关于Spring框架中动态代理的实现,Spring AOP是Spring框架的一部分,它允许我们在不修改源代码的情况下,向现有代码添加新的功能(如日志、事务管理等)。Spring AOP...