Spring(11) - Introductions进行类扩展方法
Introductions(引用),在 Aspect 中称为类型间的声明,使切面能够声明被通知的对象(拦截的对象)实现给定的接口,并提供该接口的实现。
简单点说可以将一个类的实现方法复制到未实现的类中。
通过 @DeclareParents 注解进行声明,声明在一个父类型的属性上(比如接口),其中注解的属性 value 指定对哪些路径(包)下的类进行类方法扩展,defaultImpl 指定以哪个类为模板。
如下案例:
1)切面类:
@Aspect
@Component
public class LogAspects {
@DeclareParents(value = "com.hrh.aop.*", defaultImpl = IndexDao.class)
public static Dao dao; @Pointcut("execution(public * com.hrh.aop.*.*(..))")
public void pointcut() { } @Before("pointcut()")
public void LogStart() {
System.out.println("LogStart...");
}
}
2)接口和实现类:
public interface Dao{
void query();
}
@Repository
public class IndexDao implements Dao{
public void query(){
System.out.println("query:"+this.getClass().getSimpleName());
}
}
3)配置类:
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.hrh.aop")
public class Config {
}
4)空类:
@Repository("orderDao")
public class OrderDao{}
5)测试和结果:
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
Dao bean = (Dao) context.getBean("indexDao");
bean.query();
System.out.println("----------");
Dao dao = (Dao) context.getBean("orderDao");
dao.query();
}
=========结果==========
LogStart...
query:IndexDao
----------
query:IndexDao
根据前文Spring笔记(3) - SpringAOP基础详解和源码探究可以得知如下:
- @EnableAspectJAutoProxy(proxyTargetClass=false),表示使用JDK动态代理(默认);
- @EnableAspectJAutoProxy(proxyTargetClass=true),表示使用CGLIB代理;
debug运行后查看beanFactory的OrderDao和IndexDao代理后的对象,如下图:


从上面可以看到IndexDao的对象是使用JDK代理的,而OrderDao的对象是CGLIB代理的。
那么当设置@EnableAspectJAutoProxy(proxyTargetClass=true)时,是如下图:

由此可以判定@DeclareParents注解给拦截到的类进行代理使用的是CGLIB代理(其实OrderDao没有实现任何接口,所以最终实现的是CGLIB),那么可以查看下代理类生成的内容是什么,可以在context前面加一行代码将代理类class文件存入本地磁盘:
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "xxx");//xxx是存放代理类class的本地路径
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

下面是代理类class反编译后的完整代码(感兴趣可以完全打开,完全的很多内容,包含了各种父类的方法,比如toString、clone、equals、hashCode):

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// package com.hrh.aop; import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.TargetClassAware;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Dispatcher;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.NoOp; public class OrderDao$$EnhancerBySpringCGLIB$$ee33136 extends OrderDao implements Dao, SpringProxy, Advised, Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private MethodInterceptor CGLIB$CALLBACK_1;
private NoOp CGLIB$CALLBACK_2;
private Dispatcher CGLIB$CALLBACK_3;
private Dispatcher CGLIB$CALLBACK_4;
private MethodInterceptor CGLIB$CALLBACK_5;
private MethodInterceptor CGLIB$CALLBACK_6;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$equals$0$Method;
private static final MethodProxy CGLIB$equals$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$toString$1$Method;
private static final MethodProxy CGLIB$toString$1$Proxy;
private static final Method CGLIB$hashCode$2$Method;
private static final MethodProxy CGLIB$hashCode$2$Proxy;
private static final Method CGLIB$clone$3$Method;
private static final MethodProxy CGLIB$clone$3$Proxy;
private static final Method CGLIB$query$4$Method;
private static final MethodProxy CGLIB$query$4$Proxy; static void CGLIB$STATICHOOK5() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("com.hrh.aop.OrderDao$$EnhancerBySpringCGLIB$$ee33136");
Class var1;
Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$equals$0$Method = var10000[0];
CGLIB$equals$0$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$0");
CGLIB$toString$1$Method = var10000[1];
CGLIB$toString$1$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$1");
CGLIB$hashCode$2$Method = var10000[2];
CGLIB$hashCode$2$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$2");
CGLIB$clone$3$Method = var10000[3];
CGLIB$clone$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$3");
CGLIB$query$4$Method = ReflectUtils.findMethods(new String[]{"query", "()V"}, (var1 = Class.forName("com.hrh.aop.Dao")).getDeclaredMethods())[0];
CGLIB$query$4$Proxy = MethodProxy.create(var1, var0, "()V", "query", "CGLIB$query$4");
} final boolean CGLIB$equals$0(Object var1) {
return super.equals(var1);
} public final boolean equals(Object var1) {
try {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_5;
if (this.CGLIB$CALLBACK_5 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_5;
} if (var10000 != null) {
Object var4 = var10000.intercept(this, CGLIB$equals$0$Method, new Object[]{var1}, CGLIB$equals$0$Proxy);
return var4 == null ? false : (Boolean)var4;
} else {
return super.equals(var1);
}
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} final String CGLIB$toString$1() {
return super.toString();
} public final String toString() {
try {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
} return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$1$Method, CGLIB$emptyArgs, CGLIB$toString$1$Proxy) : super.toString();
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
} final int CGLIB$hashCode$2() {
return super.hashCode();
} public final int hashCode() {
try {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_6;
if (this.CGLIB$CALLBACK_6 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_6;
} if (var10000 != null) {
Object var3 = var10000.intercept(this, CGLIB$hashCode$2$Method, CGLIB$emptyArgs, CGLIB$hashCode$2$Proxy);
return var3 == null ? 0 : ((Number)var3).intValue();
} else {
return super.hashCode();
}
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
} final Object CGLIB$clone$3() throws CloneNotSupportedException {
return super.clone();
} protected final Object clone() throws CloneNotSupportedException {
try {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
} return var10000 != null ? var10000.intercept(this, CGLIB$clone$3$Method, CGLIB$emptyArgs, CGLIB$clone$3$Proxy) : super.clone();
} catch (Error | CloneNotSupportedException | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
} final void CGLIB$query$4() {
super.query();
} public final void query() {
try {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
} if (var10000 != null) {
var10000.intercept(this, CGLIB$query$4$Method, CGLIB$emptyArgs, CGLIB$query$4$Proxy);
} else {
super.query();
}
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
} public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -1166709331:
if (var10000.equals("query()V")) {
return CGLIB$query$4$Proxy;
}
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$3$Proxy;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$0$Proxy;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$1$Proxy;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return CGLIB$hashCode$2$Proxy;
}
} return null;
} public final int indexOf(Advice var1) {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} return ((Advised)var10000.loadObject()).indexOf(var1);
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final int indexOf(Advisor var1) {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} return ((Advised)var10000.loadObject()).indexOf(var1);
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final boolean isFrozen() {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} return ((Advised)var10000.loadObject()).isFrozen();
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
} public final void setTargetSource(TargetSource var1) {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} ((Advised)var10000.loadObject()).setTargetSource(var1);
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final Advisor[] getAdvisors() {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} return ((Advised)var10000.loadObject()).getAdvisors();
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
} public final boolean isProxyTargetClass() {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} return ((Advised)var10000.loadObject()).isProxyTargetClass();
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
} public final void addAdvice(Advice var1) throws AopConfigException {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} ((Advised)var10000.loadObject()).addAdvice(var1);
} catch (Error | AopConfigException | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final void addAdvice(int var1, Advice var2) throws AopConfigException {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} ((Advised)var10000.loadObject()).addAdvice(var1, var2);
} catch (Error | AopConfigException | RuntimeException var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final boolean replaceAdvisor(Advisor var1, Advisor var2) throws AopConfigException {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} return ((Advised)var10000.loadObject()).replaceAdvisor(var1, var2);
} catch (Error | AopConfigException | RuntimeException var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final void addAdvisor(int var1, Advisor var2) throws AopConfigException {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} ((Advised)var10000.loadObject()).addAdvisor(var1, var2);
} catch (Error | AopConfigException | RuntimeException var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public final void addAdvisor(Advisor var1) throws AopConfigException {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} ((Advised)var10000.loadObject()).addAdvisor(var1);
} catch (Error | AopConfigException | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final boolean isPreFiltered() {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} return ((Advised)var10000.loadObject()).isPreFiltered();
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
} public final boolean removeAdvice(Advice var1) {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} return ((Advised)var10000.loadObject()).removeAdvice(var1);
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final void removeAdvisor(int var1) throws AopConfigException {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} ((Advised)var10000.loadObject()).removeAdvisor(var1);
} catch (Error | AopConfigException | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final boolean removeAdvisor(Advisor var1) {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} return ((Advised)var10000.loadObject()).removeAdvisor(var1);
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final TargetSource getTargetSource() {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} return ((Advised)var10000.loadObject()).getTargetSource();
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
} public final void setPreFiltered(boolean var1) {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} ((Advised)var10000.loadObject()).setPreFiltered(var1);
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final boolean isExposeProxy() {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} return ((Advised)var10000.loadObject()).isExposeProxy();
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
} public final void setExposeProxy(boolean var1) {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} ((Advised)var10000.loadObject()).setExposeProxy(var1);
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final Class[] getProxiedInterfaces() {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} return ((Advised)var10000.loadObject()).getProxiedInterfaces();
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
} public final boolean isInterfaceProxied(Class var1) {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} return ((Advised)var10000.loadObject()).isInterfaceProxied(var1);
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public final String toProxyConfigString() {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} return ((Advised)var10000.loadObject()).toProxyConfigString();
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
} public final Class getTargetClass() {
try {
Dispatcher var10000 = this.CGLIB$CALLBACK_4;
if (this.CGLIB$CALLBACK_4 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_4;
} return ((TargetClassAware)var10000.loadObject()).getTargetClass();
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
} public OrderDao$$EnhancerBySpringCGLIB$$ee33136() {
try {
super();
CGLIB$BIND_CALLBACKS(this);
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
} public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
} public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
} private static final void CGLIB$BIND_CALLBACKS(Object var0) {
OrderDao$$EnhancerBySpringCGLIB$$ee33136 var1 = (OrderDao$$EnhancerBySpringCGLIB$$ee33136)var0;
if (!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if (var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if (CGLIB$STATIC_CALLBACKS == null) {
return;
}
} Callback[] var10001 = (Callback[])var10000;
var1.CGLIB$CALLBACK_6 = (MethodInterceptor)((Callback[])var10000)[6];
var1.CGLIB$CALLBACK_5 = (MethodInterceptor)var10001[5];
var1.CGLIB$CALLBACK_4 = (Dispatcher)var10001[4];
var1.CGLIB$CALLBACK_3 = (Dispatcher)var10001[3];
var1.CGLIB$CALLBACK_2 = (NoOp)var10001[2];
var1.CGLIB$CALLBACK_1 = (MethodInterceptor)var10001[1];
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)var10001[0];
} } public Object newInstance(Callback[] var1) {
try {
CGLIB$SET_THREAD_CALLBACKS(var1);
OrderDao$$EnhancerBySpringCGLIB$$ee33136 var10000 = new OrderDao$$EnhancerBySpringCGLIB$$ee33136();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public Object newInstance(Callback var1) {
try {
throw new IllegalStateException("More than one callback object required");
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
try {
CGLIB$SET_THREAD_CALLBACKS(var3);
OrderDao$$EnhancerBySpringCGLIB$$ee33136 var10000 = new OrderDao$$EnhancerBySpringCGLIB$$ee33136;
switch(var1.length) {
case 0:
var10000.<init>();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
default:
throw new IllegalArgumentException("Constructor not found");
}
} catch (Error | RuntimeException var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
} public Callback getCallback(int var1) {
try {
CGLIB$BIND_CALLBACKS(this);
Object var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
case 1:
var10000 = this.CGLIB$CALLBACK_1;
break;
case 2:
var10000 = this.CGLIB$CALLBACK_2;
break;
case 3:
var10000 = this.CGLIB$CALLBACK_3;
break;
case 4:
var10000 = this.CGLIB$CALLBACK_4;
break;
case 5:
var10000 = this.CGLIB$CALLBACK_5;
break;
case 6:
var10000 = this.CGLIB$CALLBACK_6;
break;
default:
var10000 = null;
} return (Callback)var10000;
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} public void setCallback(int var1, Callback var2) {
try {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
break;
case 1:
this.CGLIB$CALLBACK_1 = (MethodInterceptor)var2;
break;
case 2:
this.CGLIB$CALLBACK_2 = (NoOp)var2;
break;
case 3:
this.CGLIB$CALLBACK_3 = (Dispatcher)var2;
break;
case 4:
this.CGLIB$CALLBACK_4 = (Dispatcher)var2;
break;
case 5:
this.CGLIB$CALLBACK_5 = (MethodInterceptor)var2;
break;
case 6:
this.CGLIB$CALLBACK_6 = (MethodInterceptor)var2;
} } catch (Error | RuntimeException var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
} public Callback[] getCallbacks() {
try {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0, this.CGLIB$CALLBACK_1, this.CGLIB$CALLBACK_2, this.CGLIB$CALLBACK_3, this.CGLIB$CALLBACK_4, this.CGLIB$CALLBACK_5, this.CGLIB$CALLBACK_6};
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
} public void setCallbacks(Callback[] var1) {
try {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
this.CGLIB$CALLBACK_1 = (MethodInterceptor)var1[1];
this.CGLIB$CALLBACK_2 = (NoOp)var1[2];
this.CGLIB$CALLBACK_3 = (Dispatcher)var1[3];
this.CGLIB$CALLBACK_4 = (Dispatcher)var1[4];
this.CGLIB$CALLBACK_5 = (MethodInterceptor)var1[5];
this.CGLIB$CALLBACK_6 = (MethodInterceptor)var1[6];
} catch (Error | RuntimeException var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
} static {
CGLIB$STATICHOOK6();
CGLIB$STATICHOOK5();
} static void CGLIB$STATICHOOK6() {
try {
;
} catch (Error | RuntimeException var0) {
throw var0;
} catch (Throwable var1) {
throw new UndeclaredThrowableException(var1);
}
}
}
从上面可以看到代理类里面有query方法,代理类继承了OrderDao和实现了Dao接口:
public class OrderDao$$EnhancerBySpringCGLIB$$ee33136 extends OrderDao implements Dao, SpringProxy, Advised, Factory {
............................
final void CGLIB$query$4() {
super.query();
}
public final void query() {
try {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$query$4$Method, CGLIB$emptyArgs, CGLIB$query$4$Proxy);
} else {
super.query();
}
} catch (Error | RuntimeException var1) {
throw var1;
} catch (Throwable var2) {
throw new UndeclaredThrowableException(var2);
}
}
............................
}
从前文Spring笔记(3) - SpringAOP基础详解和源码探究可以得知在 AbstractAutoProxyCreator#wrapIfNecessary()中会对bean进行包装增强(代理),下面打下断点debug跟踪下流程:


当执行到wrapIfNecessary方法下面的代码时,bean还是原对象(未被代理):
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

当上面的代码执行完后,可以看到specificInterceptors数组包含了advice(通知)、introducedInterface(引用接口)、typePatternClassFilter(class过滤规则,重点),其中advice包含了defaultImplType(默认实现类型,上面代码中定义的),可以看到是IndexDao,interfaceType(接口类型)可以看到是Dao,以上信息是通过解析@DeclareParents注解而来的:

下面typePatternClassFilter里面的详情,可以看到,上面的信息又包含在typePatternClassFilter里面,同时里面包含了过滤规则:

最后通过DefaultAopProxyFactory#createAopProxy方法创建的对象如下图:

当执行query方法时,CglibAopProxy.DynamicAdvisedInterceptor#intercept方法进行拦截时,会执行父类的方法ReflectiveMethodInvocation#ReflectiveMethodInvocation:



执行完会跳转到ReflectiveMethodInvocation#proceed执行方法的执行:
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);
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);//执行方法
}
}

下面执行delegate对象获取到IndexDao,然后AopUtils.invokeJoinpointUsingReflection执行IndexDao的query实现方法:


其中getIntroductionDelegateFor方法中的delegate通过反射对默认实现类型进行构造方法实例化后调用实例化的方法:



总结:Introductions(引用)通过 @DeclareParents 注解实现,可以给一个空白类进行方法复制,它通过解析@DeclareParents 注解信息,代理时将定义的静态接口变量作为它的父类,并实现它的方法,方法执行时调用的是defaultImpl 指定的类模板的实现方法;
Spring(11) - Introductions进行类扩展方法的更多相关文章
- MBProgressHUD 的类扩展方法用法
#import "MBProgressHUD.h" @interface MBProgressHUD (Add) + (void)showError:(NSString *)err ...
- C#语法糖: 扩展方法(常用)
今天继续分享C#4.0语法糖的扩展方法,这个方法也是我本人比较喜欢的方法.大家先想想比如我们以前写的原始类型不能满足现在的需求,而需要在该类型中添加新的方法来实现时大家会怎么做.我先说一下我没有学习到 ...
- .NET 扩展方法
.NET 的扩展方法是在.NET 3.0引入的,MSDN给出的定义是:扩展方法使你能够向现有类型“添加”方法(包括你自定义的类型和对象噢),而无需创建新的派生类型.重新编译或以其他方式修改原始类型.扩 ...
- Linq之扩展方法
目录 写在前面 系列文章 扩展方法 总结 写在前面 上篇文章介绍了隐式类型,自动属性,初始化器,匿名类的相关概念,及通过反编译的方式查看了编译器帮我们做了那些事.本篇文章将介绍扩展方法的知识点,及如何 ...
- MVC中使用HTML Helper类扩展HTML控件
文章摘自:http://www.cnblogs.com/zhangziqiu/archive/2009/03/18/1415005.html MVC在view页面,经常需要用到很多封装好的HTML控件 ...
- C#语法糖之第四篇: 扩展方法
今天继续分享C#4.0语法糖的扩展方法,这个方法也是我本人比较喜欢的方法.大家先想想比如我们以前写的原始类型不能满足现在的需求,而需要在该类型中添加新的方法来实现时大家会怎么做.我先说一下我没有学习到 ...
- 将基于Nullable<T>的类型转换实现在扩展方法中
三.将基于Nullable<T>的类型转换实现在扩展方法中 从上面的介绍我们可以得出这样的结论:如果类型T1和T2能够相互兼容,我们可以借助Convert将T1类型对象转换成T2类型,然后 ...
- OC分类(类目/类别) 和 类扩展 - 全解析
OC分类(类目/类别) 和 类扩展 - 全解析 具体见: oschina -> MyDemo -> 011.FoundationLog-OC分类剖析 http://blog.csdn. ...
- C#扩展方法学习
扩展方法的本质是什么,详细见此文 C#扩展方法,爱你在心口难开 重点如下:扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型.扩展方法是一种特殊的静态方法 ...
随机推荐
- vue监听生命周期
监听生命周期事件 内部监听声明周期函数 data() { return { monitor: null }; }, mounted() { this.monitor = setInterval(() ...
- pytorch(06)autograd与逻辑回归
autograd与逻辑回归 自动求导系统中两个常用的方法: torch.autograd.backward and torch.autograd.grad 演示理解一阶导数.二阶导数的求导过程 理解自 ...
- 设计模式系列之原型模式(Prototype Pattern)——对象的克隆
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
- springmvc redis @Cacheable扩展(一)
springmvc 中有自带的cache处理模块,可以是方法级别的缓存处理,那么在实际使用中,很可能自己造轮子,因为实际中永远会有更奇怪的需求点.比如: 1 清除缓存时候,能模糊的进行删除 2 针对不 ...
- 如何自学成 Python 大神?这里有些建议
人生苦短,我用 Python.为什么?简单明了的理由当然是开发效率高.但是学习 Python 的初学者往往会面临以下残酷的现状:网上充斥着大量的学习资源.书籍.视频教程和博客,但是大部分都是讲解基础知 ...
- 优化自动化测试流程,使用 flask 开发一个 toy jenkins工具
1.自动化 某一天你入职了一家高大上的科技公司,开心的做着软件测试的工作,每天点点点,下班就走,晚上陪女朋友玩王者,生活很惬意. 但是美好时光一般不长,这种生活很快被女主管打破.为了提升公司测试效率, ...
- C# 应用 - 使用 WebClient 发起 Http 请求
1. 需要的库类 \Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.dll System.Net.WebCli ...
- WPF 基础 - 事件
1. 前言 WPF 事件的路由环境是 UI 组件树,先来看看这棵树. 1.1 Logical Tree 和 Visual Tree WPF 中的树有两种,一颗是逻辑树,另一颗也是逻辑树. 开玩笑,WP ...
- Java流程控制:三种基本结构
顺序结构: Java的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行顺序结构是最简单的算法结构语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的, ...
- Windows下的Linux子系统
强调!!!必须是Windows专业版!!! 一.安装运行过程 第一步:打开开发人员模式 第二步:进入 '控制面板 '--'程序'--'启用的Windows功能'--勾选Linux子系统(根据提示进行重 ...