(七)重点看了spring aop的各个主要接口的定义,以及简单分析了各个主要方法的作用,
这节主要了解spring是怎么利用jdk\cglib 来实现的前置通知、环绕通知等等
通过(七)中查看AbstractAutoProxyCreator类时,可以知道spring创建代理对象是通过ProxyFactory来创建的。
那么这里就从ProxyFactory开始
1、查看分析spring创建Aop的工厂类ProxyFactory,及其相关父类(Aop配置类)
首先查看该类的相关的类图如下
ProxyConfig 管理创建proxy的基本陪配置
TargetClassAware 定义了获取proxy目标对象class对象的方法
Advised主要是定义了与配置代理对象的通知相关的一些方法
AdvisedSupport是对Advised接口的实现类,实现配置管理Advicor
ProxyCreatorSupport 实现创建proxy对象
ProxyFactory 对编程式aop代理创建的支持
ProxyFactoryBean 对基于BeanFactory的aop代理创建的支持
(与编程式aop类似,主要是提供面向配置支持,结合bean容器对FactoryBean的支持,就像直接操作代理对象一样)
AspectJProxyFactory spring对解析基于aspectj风格的方面配置来创建代理对象的支持
下面是ProxyConfig中定义的配置
public class ProxyConfig implements Serializable {
//是否是对目标类做代理(spring aop利用该配置决定是使用cglib还是jdk动态代理)
private boolean proxyTargetClass = false;
//是否尝试最佳化配置
private boolean optimize = false;
//是否非透明化处理(是否不暴露aop配置)
boolean opaque = false;
//是否给目标方法暴露代理对象Aop
boolean exposeProxy = false;
//冻结配置
private boolean frozen = false;
}
通过该类定义的内容可以看到,ProxyConfig 应该是主要负责管理创建proxy需要的一些配置信息
public interface TargetClassAware {
@Nullable
Class<?> getTargetClass();
}
在对目标进行创建代理时jdk是基于接口、cglib是基于目标class对象
TargetClassAware 用来获取proxy目标类class对象,可以用来创建代理对象使用
public interface Advised extends TargetClassAware {
boolean isFrozen();
boolean isProxyTargetClass();
Class<?>[] getProxiedInterfaces();
boolean isInterfaceProxied(Class<?> intf);
void setTargetSource(TargetSource targetSource);
TargetSource getTargetSource();
void setExposeProxy(boolean exposeProxy);
boolean isExposeProxy();
void setPreFiltered(boolean preFiltered);
boolean isPreFiltered();
Advisor[] getAdvisors();
void addAdvisor(Advisor advisor) throws AopConfigException;
void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
boolean removeAdvisor(Advisor advisor);
void removeAdvisor(int index) throws AopConfigException;
int indexOf(Advisor advisor);
boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
void addAdvice(Advice advice) throws AopConfigException;
void addAdvice(int pos, Advice advice) throws AopConfigException;
boolean removeAdvice(Advice advice);
int indexOf(Advice advice);
String toProxyConfigString();
}
从接口中的方法可以看出,Advised主要是定义了与配置代理对象的通知相关的一些方法
AdvisedSupport的代理这里就不贴出来了,它主要是继承ProxyConfig并实现了通知相关的配置功能,为下面代理创建提供基本的配置支持。
public class ProxyCreatorSupport extends AdvisedSupport {
//...
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
//...
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
//...
}
实际创建aop代理对象的逻辑是在DefaultAopProxyFactory中实现的。
在这几个类和接口中主要是定义了aop代理创建的配置信息。
下面查看AopProxyFactory看具体创建代理对象的逻辑
2、代理对象工厂AopProxyFactory
AopProxyFactory接口中就定义了一个工厂方法,
AdvisedSupport 属于aop创建的配置,统一返回AopProxy
public interface AopProxyFactory {
AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;
}
下面查看AopProxy接口的定义
public interface AopProxy {
//创建代理对象
Object getProxy();
//指定类加载器来创建代理对象
Object getProxy(@Nullable ClassLoader classLoader);
}
从AopProxy接口定义的方法可以看出,
AopProxyFactory并不是创建代理对象的工厂,而是创建代理对象工厂的工厂。
AopProxy才是代理对象的工厂
查看AopProxyFactory的实现类DefaultAopProxyFactory
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
//目标是接口或者jdk代理类 使用jdk创建代理
return new JdkDynamicAopProxy(config);
}
//使用cglib创建代理
return new ObjenesisCglibAopProxy(config);
}
else {
//使用jdk创建代理
return new JdkDynamicAopProxy(config);
}
}
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
}
3、用来创建代理对象的AopProxy
至此就能看到spring是怎么利用cglib、jdk动态代理 来实现 (七)中提到的各种方面的了。
首先从较为熟悉的JdkDynamicAopProxy开始
从JdkDynamiAopProxy实现的接口上可以看出,该类不光是定义了创建Aop代理对象,而且还是代理对象的执行处理器(java.lang.reflect.InvocationHandler)
熟悉jdk代理的话,可以知道InvocationHandler会在代理对象执行目标接口的方法时去直接调用invocationHandler.invoke(..)方法
如果要进行aop编程则直接在invoke实现方法中定义自己的方面即可,因此如果想要知道spring的方面是怎么实现的,直接看invoke方法即可。
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
//...
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
//这里会为目标对象引入一些附加接口①
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//创建代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
//...
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
//如果目标未实现equals方法使用,统一使用这里定义的equals
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
//同equals
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
// 代理实现的decoratingProxy.getDecoratedClass() 用来获取代理目标的class对象
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
// 如果在前面的aop基本配置中配置了opaque = false(透明化aop配置),这里对所有Advised接口中定义的方法都可以使用代理对象调用获取到aop的配置
// 连接点调用 实际就是使用反射调用方法method.invoke(target, args)
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
// 下面是非特殊方法的调用
Object retVal;
//通过这一步可以看到exposeProxy 的作用是可以通过AopContext在方法内部调用AopContext.currentProxy() 获取当前方法的代理对象
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
// targetSource.getTarget()获取的就是代理目标对象
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
// 通过目标类和方法,来获取对应的方面
// 这里会设置到切入点的判断PointcutAdvisor IntroductionAdvisor ...
// 如pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)... 然后获取符合当前方法的Advisor
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 没有匹配到对应的advisor就直接执行目标方法
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
// 要执行的目标方法就是一个连接点,这里就是将方法包装成连接点,而方面Advisors也直接包装进去了,这样方面的执行就委托给了这个连接点来实现了
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
// 执行连接点(连接点中是怎么执行方面的,后面查看)
retVal = invocation.proceed();
}
// Massage return value if necessary.
// 如果目标方法返回值是this 这里进行特殊处理了一下,防止直接返回了目标对象,将返回值替换为代理对象
// RawTargetAccess是类型标记接口,如果目标对象实现了该方法则直接返回代理目标对象
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
// 从哪来到哪去
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
// 这个是aop嵌套调用时满足各层都能正确得到当前方法的代理对象
AopContext.setCurrentProxy(oldProxy);
}
}
}
//...
}
下面查看ReflectiveMethodInvocation.proceed()部门的代码,了解连接点调用(实际上是方面 + 连接点调用)
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
//...
protected ReflectiveMethodInvocation(
Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
@Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
this.proxy = proxy;
this.target = target;
this.targetClass = targetClass;
this.method = BridgeMethodResolver.findBridgedMethod(method);
this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
//方面Advisors
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
//...
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// 如果是最后一轮,执行连接点
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 这里是对动态aop的支持(根据方法入参 决定是否执行方面)
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
// 执行方面
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
//...
}
这里利用方法递归来实现方面的执行的,时序图如下(假设只有两个Interceptor)。
可以看到这种递归调用 都是基于ReflectiveMethodInvocation中的proceed方法的,等于是它来负责处理递归逻辑,而对于自定义的Interceptor只需要关注
实现方面逻辑,无需维护递归逻辑。
cglib创建代理对象的过程与jdk动态代理类似
class CglibAopProxy implements AopProxy, Serializable {
//...
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
//如果代理目标类已经是cglib的代理类,获取父类进行代理
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
// 用来创建cglib代理子类的核心类,类似于jdk的Proxy
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
//配置代理目标类
enhancer.setSuperclass(proxySuperClass);
//要代理的接口
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
//cglib的代理回调方法 类似于jdk的InvocationHandler 不过Callback只是一个标记接口,并未定义任何方法,其子接口定义了各种类型的回调形式
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
// 设置过滤器,相当于spring的pointcut 用来匹配目标方法来决定是否创建代理子类方法
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
// 生成代理对象实例
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
//...
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimization choices...
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// Choose an "aop" interceptor (used for AOP calls).
// 该类实现的是org.springframework.cglib.proxy.MethodInterceptor 与jdk的InvocationHandler中的invoke方法类似,属于代理方法的回调
// DynamicAdvisedInterceptor实现与上面jdk的JdkDynamicAopProxy中invoke方法实现类似,用来实现方面以及连接点调用
// 这里主要是实现的spring aop
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// Choose a "straight to target" interceptor. (used for calls that are
// unadvised but can return this). May be required to expose the proxy.
Callback targetInterceptor;
if (exposeProxy) {
targetInterceptor = isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
}
else {
targetInterceptor = isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
}
// Choose a "direct to target" dispatcher (used for
// unadvised calls to static targets that cannot return this).
Callback targetDispatcher = isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();
//对于上面给enhancer设置的CallbackFilter spring分别定义了几个数字来表示对应哪个Interceptor
//private static final int AOP_PROXY = 0;
//rivate static final int INVOKE_TARGET = 1;
//private static final int NO_OVERRIDE = 2;
//private static final int DISPATCH_TARGET = 3;
//private static final int DISPATCH_ADVISED = 4;
//private static final int INVOKE_EQUALS = 5;
//private static final int INVOKE_HASHCODE = 6;
//与下面这几个一一对应
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
new SerializableNoOp(), // no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,
// then we can make some optimizations by sending the AOP calls
// direct to the target using the fixed chain for that method.
// 下面是对方法对应哪些Callback作的一层优化,可以直接根据 fixedInterceptorMap 获取直接通过idx + offset 得到当前方法对应需要执行的Interceptor
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<>(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice)
for (int x = 0; x < methods.length; x++) {
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(methods[x].toString(), x);
}
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
//...
}
4、编程式创建spring aop对象
通过上面的了解,现在对spring aop的实现 有了更深的认识。
下面就基于spring编程式aop,来实现aop代理的创建。
public class SpringAopDemo {
@Test
public void demo1() throws Exception {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setProxyTargetClass(false);
proxyFactory.setFrozen(false);
proxyFactory.setOpaque(false); //设置将aop配置透明化处理
proxyFactory.setExposeProxy(true); //给被切入的方法暴露proxy对象
proxyFactory.addAdvice(new MethodBeforeAdviceInterceptor(new MethodBeforeAdvice() {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("前置通知");
}
}) {
@Override
public String toString() {
return "前置通知";
}
});
proxyFactory.addAdvice(new AfterReturningAdviceInterceptor(new AfterReturningAdvice() {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("正常返回通知");
}
}){
@Override
public String toString() {
return "正常返回通知";
}
});
proxyFactory.addAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("拦截环绕通知-前");
Object retVal = invocation.proceed();
System.out.println("拦截环绕通知-后");
return retVal;
}
@Override
public String toString() {
return "环绕通知";
}
});
proxyFactory.addAdvice(new ThrowsAdviceInterceptor(new ThrowingAdvice()){
@Override
public String toString() {
return "异常通知";
}
});
proxyFactory.setTarget(new TargetObject());
Say proxy = (Say) proxyFactory.getProxy();
proxy.doSay();
}
interface Say {
void doSay();
}
class TargetObject implements Say {
public void doSay() {
Object currentProxy = AopContext.currentProxy();
System.out.println("\t\t\t当前代理:" + currentProxy);
Advised advised = (Advised) currentProxy;
System.out.println("\t\t\t设置AOP配置透明化处理,AOP配置信息:" + Arrays.toString(advised.getAdvisors()));
System.out.println("\t\t\tproxy class:" + currentProxy.getClass());
System.out.println("\t\t\ttarget class:" + ((TargetClassAware) currentProxy).getTargetClass());
System.out.println("hello word.");
//throw new RuntimeException("异常了。。。");
}
}
public class ThrowingAdvice {
public void afterThrowing(Throwable t) {
System.out.println("异常通知:" + t.getMessage());
}
}
}
控制台输出结果:
前置通知
拦截环绕通知-前
①前置通知
②拦截环绕通知-前
③拦截环绕通知-后
④正常返回通知
当前代理:com.example.lcc.basic.spring.aop.SpringAopDemo$TargetObject@1bce4f0a
设置AOP配置透明化处理,AOP配置信息:[org.springframework.aop.support.DefaultPointcutAdvisor: pointcut [Pointcut.TRUE]; advice [前置通知], org.springframework.aop.support.DefaultPointcutAdvisor: pointcut [Pointcut.TRUE]; advice [正常返回通知], org.springframework.aop.support.DefaultPointcutAdvisor: pointcut [Pointcut.TRUE]; advice [环绕通知], org.springframework.aop.support.DefaultPointcutAdvisor: pointcut [Pointcut.TRUE]; advice [异常通知]]
proxy class:class com.example.lcc.basic.spring.aop.SpringAopDemo$TargetObject$$EnhancerBySpringCGLIB$$e8b223a8
target class:class com.example.lcc.basic.spring.aop.SpringAopDemo$TargetObject
hello word.
拦截环绕通知-后
正常返回通知
在查看控制台结果时会发现多出①②③④ 这四句看似不应该出现的输出,开始还以为是哪里出了问题,仔细分析了下代码才发现,
在这句:System.out.println("\t\t\t当前代理:" + currentProxy); 实际是调用了currentProxy.toString()方法
toString方法也是个代理方法,会引入方面的Advice因此①②③④ 其实是toString()触发的方面执行,
另外在debug时,如图:
会发现每走一步,控制台都会重复输出①②③④
前置通知
拦截环绕通知-前
拦截环绕通知-后
正常返回通知
前置通知
拦截环绕通知-前
拦截环绕通知-后
正常返回通知
前置通知
拦截环绕通知-前
拦截环绕通知-后
正常返回通知
前置通知
拦截环绕通知-前
拦截环绕通知-后
正常返回通知
//...
这是因为IDEA debug时会自动尝试获取对象的toString()输出展示到当前行的后面(注意图片中的灰体部分),
又因为toString方法是被代理的方法,因此会产生看似不可思议的结果。
总结:
spring aop属于一套spring风格的api,它是通过jdk动态代理、与cglib的动态代理来实现的这套api,而且对于由spring bean容器管理的对象,使用aop会非常的
方便,但是如果想对那些不是由spring容器管理的对象进行方面编程,就没办法了。如:对pojo的方面编程,那样就需要通过其他aop框架来实现了,如aspectj。
使用spring aop对比aspectj的好处就是无需在开发和构建过程中 引入专用的compiler/weaver,坏处就是spring aop局限于要将对象交给它来管理才能使用。