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进行类扩展方法的更多相关文章

  1. MBProgressHUD 的类扩展方法用法

    #import "MBProgressHUD.h" @interface MBProgressHUD (Add) + (void)showError:(NSString *)err ...

  2. C#语法糖: 扩展方法(常用)

    今天继续分享C#4.0语法糖的扩展方法,这个方法也是我本人比较喜欢的方法.大家先想想比如我们以前写的原始类型不能满足现在的需求,而需要在该类型中添加新的方法来实现时大家会怎么做.我先说一下我没有学习到 ...

  3. .NET 扩展方法

    .NET 的扩展方法是在.NET 3.0引入的,MSDN给出的定义是:扩展方法使你能够向现有类型“添加”方法(包括你自定义的类型和对象噢),而无需创建新的派生类型.重新编译或以其他方式修改原始类型.扩 ...

  4. Linq之扩展方法

    目录 写在前面 系列文章 扩展方法 总结 写在前面 上篇文章介绍了隐式类型,自动属性,初始化器,匿名类的相关概念,及通过反编译的方式查看了编译器帮我们做了那些事.本篇文章将介绍扩展方法的知识点,及如何 ...

  5. MVC中使用HTML Helper类扩展HTML控件

    文章摘自:http://www.cnblogs.com/zhangziqiu/archive/2009/03/18/1415005.html MVC在view页面,经常需要用到很多封装好的HTML控件 ...

  6. C#语法糖之第四篇: 扩展方法

    今天继续分享C#4.0语法糖的扩展方法,这个方法也是我本人比较喜欢的方法.大家先想想比如我们以前写的原始类型不能满足现在的需求,而需要在该类型中添加新的方法来实现时大家会怎么做.我先说一下我没有学习到 ...

  7. 将基于Nullable<T>的类型转换实现在扩展方法中

    三.将基于Nullable<T>的类型转换实现在扩展方法中 从上面的介绍我们可以得出这样的结论:如果类型T1和T2能够相互兼容,我们可以借助Convert将T1类型对象转换成T2类型,然后 ...

  8. OC分类(类目/类别) 和 类扩展 - 全解析

    OC分类(类目/类别) 和 类扩展 - 全解析   具体见: oschina -> MyDemo -> 011.FoundationLog-OC分类剖析 http://blog.csdn. ...

  9. C#扩展方法学习

    扩展方法的本质是什么,详细见此文 C#扩展方法,爱你在心口难开 重点如下:扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型.扩展方法是一种特殊的静态方法 ...

随机推荐

  1. 随手一记,关于Java日期时间格式化

    在Java中,我们大多数情况下格式化日期都是使用simpleDateFormat,比如把一个日期格式化成:2019-12-31的形式,我们一般定义模板为:yyyy-MM-dd的形式. 我们需要注意的是 ...

  2. 带你认识webpack

    一.webpack是什么 webpack是一种前端资源构建工具,一个静态模块打包器(module bundler).在webpack看来,前端的所有资源文件(js/json/css/img/less/ ...

  3. 如何将文件夹取消svn关联

    随便在什么目录新建一个文本文件,文件名随便,将文本文件打开,将下面的文字复制到文本文件中: Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHI ...

  4. 痞子衡嵌入式:盘点国内RISC-V内核MCU厂商

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是国内RISC-V内核MCU厂商. 虽然RISC-V风潮已经吹了好几年,但2019年才是其真正进入主流市场的元年,最近国内大量芯片公司崛起 ...

  5. ValidationUtils 验证工具

    package com.appnirman.vaidationutils;import android.content.Context;import java.util.regex.Matcher;i ...

  6. Bootstrap下拉菜单、按钮式下拉菜单

    1. 概述 下拉菜单使用频率也是比较高的,比较常见的使用场景是在导航菜单栏,某个主菜单含有下拉的子菜单. Bootstrap为下拉菜单提供了两种实现方式,即普通的下拉菜单还有按钮式的下拉菜单.我们先看 ...

  7. Aliyun Oss 上传文件

    目录 Aliyun OSS OSS 简介 OSS 基本概念 OSS 功能概述 OSS 使用 创建存储空间Bucket 创建子目录 Java编码 测试 Aliyun OSS OSS 简介 阿里云对象存储 ...

  8. C++入门(2):为何还学C++?

    本文首发 | 公众号:lunvey 提及编程语言,最近很火的当属Python和Java,似乎C++没落了,真的是这样吗? 转行做程序员,掌握一门编程语言,也就是职业技能,我相信更多的是在乎未来发展而不 ...

  9. POJ-1458(LCS:最长公共子序列模板题)

    Common Subsequence POJ-1458 //最长公共子序列问题 #include<iostream> #include<algorithm> #include& ...

  10. Java 面向对象 02

    面向对象·二级 构造方法Constructor概述和格式 * A:构造方法概述和作用     * 给对象的数据(属性)进行初始化 * B:构造方法格式特点     * a:方法名与类名相同(大小也要与 ...