上篇中的自定义Advisor是实现的AbstractPointcutAdvisor,Advisor其实还有一个接口级别的IntroductionAdvisor

                   

这个好像用的很少,网上搜了一些资料,说是基于Class的增强,接口的功能扩展,在原有的功能上增加一些其他接口定义的方法,可以将当前代理对象向上转型,然后调用接口中的方法

这个功能暂时还不知道适用于什么场景

示例:

//定义一个some类,只有doSome方法
@Component
public class Some {
public void doSome() {
System.out.println("do some...");
};
}
//定义一个other接口,提供doOther功能
public interface IOther {
public void doOther();
}
//定义一个通知器
@Component
public class OtherIntroductionAdvisor extends DefaultIntroductionAdvisor { public OtherIntroductionAdvisor() {
super(new OtherIntroductionInterceptor());
} // createBean的时候判断bean是否需要被代理
@Override
public boolean matches(Class<?> clazz) {
//只代理some对象
boolean assignableFrom = clazz.isAssignableFrom(Some.class);
return assignableFrom;
}
}
//定义一个通知,要实现IOther接口
public class OtherIntroductionInterceptor implements IntroductionInterceptor, IntroductionInfo, IOther { //实现doOther方法
@Override
public void doOther() {
System.out.println("do other ...");
} //扩展功能的实现
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
//当前方法的声明类是否实现了需要拓展功能的接口
if (implementsInterface(invocation.getMethod().getDeclaringClass())) {
//调用this的此方法
return invocation.getMethod().invoke(this, invocation.getArguments());
}
return invocation.proceed();
} @Override
public boolean implementsInterface(Class<?> ifc) {
Class<?>[] interfaces = this.getInterfaces();
for (Class clazz : interfaces) {
if (ifc.isInterface() && ifc.isAssignableFrom(clazz)) {
return true;
}
}
return false;
} @Override
public Class<?>[] getInterfaces() {
return new Class[] {IOther.class};
}
}

在创建代理对象时,将拓展功能的接口set进去,所以代理对象上转型才不会报错

org.springframework.aop.framework.CglibAopProxy#getProxy(java.lang.ClassLoader)

@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;
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...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
// 获取接口信息并且set到代理对象的接口中
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); 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
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 " + 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);
}
}

3.AOP中的IntroductionAdvisor的更多相关文章

  1. Spring AOP中定义切点(PointCut)和通知(Advice)

    如果你还不熟悉AOP,请先看AOP基本原理,本文的例子也沿用了AOP基本原理中的例子.切点表达式 切点的功能是指出切面的通知应该从哪里织入应用的执行流.切面只能织入公共方法.在Spring AOP中, ...

  2. 正确理解Spring AOP中的Around advice

    Spring AOP中,有Before advice和After advice,这两个advice从字面上就可以很容易理解,但是Around advice就有点麻烦了. 乍一看好像是Before ad ...

  3. Spring AOP中的动态代理

    0  前言 1  动态代理 1.1 JDK动态代理 1.2 CGLIB动态代理 1.2.1 CGLIB的代理用法 1.2.2 CGLIB的过滤功能 2  Spring AOP中的动态代理机制 2.1  ...

  4. Spring AOP高级——源码实现(2)Spring AOP中通知器(Advisor)与切面(Aspect)

    本文例子完整源码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/Spring%20AOP%E9%A ...

  5. 笔记13 AOP中After和AfterReturning的区别

    AOP中 @Before @After @AfterThrowing@AfterReturning的执行顺序 public Object invoke(Object proxy, Method met ...

  6. spring aop中pointcut表达式完整版

    spring aop中pointcut表达式完整版 本文主要介绍spring aop中9种切入点表达式的写法 execute within this target args @target @with ...

  7. Spring AOP中的JDK和CGLib动态代理哪个效率更高?

    一.背景 今天有小伙伴面试的时候被问到:Spring AOP中JDK 和 CGLib动态代理哪个效率更高? 二.基本概念 首先,我们知道Spring AOP的底层实现有两种方式:一种是JDK动态代理, ...

  8. 转:Spring AOP中的动态代理

    原文链接:Spring AOP中的动态代理 0  前言 1  动态代理 1.1 JDK动态代理 1.2 CGLIB动态代理 1.2.1 CGLIB的代理用法 1.2.2 CGLIB的过滤功能 2  S ...

  9. Spring AOP 中@Pointcut的用法

    Spring Aop中@pointCut的用法,格式:execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? nam ...

随机推荐

  1. 在eclipse导入项目的步骤

    1. Import 2. Next 3. 确定  选中copy projects into workspace    Finish 这样项目就导入进来了. 4.导入jar包 Configure Bui ...

  2. 【Distributed】限流技巧

    一.概述 1.1 高并发服务限流特技 1.2 为什么要互联网项目要限流 1.3 高并发限流解决方案 二.限流算法 2.1 计数器 2.2 滑动窗口计数 2.3 令牌桶算法 使用RateLimiter实 ...

  3. Go语言根据数据表自动生成model以及controller代码

    手写model的用法请参考: https://www.jianshu.com/p/f5784b8c00d0 这里仅说明自动生成model文件的过程 bee generate appcode -tabl ...

  4. linecache:高效的读取文本文件

    介绍  可以很方便的读取文件 读取特定行 import linecache ''' 我们常用的序列的索引是从0开始的,但是linecache模块读取的文件行号是从1开始的 ''' # 表示读取C:\p ...

  5. 《浏览器工作原理与实践》<06>渲染流程(下):HTML、CSS和JavaScript,是如何变成页面的?

    在上篇文章中,我们介绍了渲染流水线中的 DOM 生成.样式计算和布局三个阶段,那今天我们接着讲解渲染流水线后面的阶段. 这里还是先简单回顾下上节前三个阶段的主要内容:在 HTML 页面内容被提交给渲染 ...

  6. 抽象类能使用 final 修饰吗?(未完成)

    抽象类能使用 final 修饰吗?(未完成)

  7. Python&Selenium 数据驱动【unittest+ddt+json】

    一.摘要 本博文将介绍Python和Selenium做自动化测试的时候,基于unittest框架,借助ddt模块使用json文件作为数据文件作为测试输入,最后生成html测试报告 二.json文件 [ ...

  8. golang 中Pointers Vs References

    原文: https://spf13.com/post/go-pointers-vs-references/ Pointers Vs References Some languages includin ...

  9. import this: python原则

    >>> import this The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is ...

  10. 二叉堆的应用——查找长度为N数组中第M大数

    看到这个题目首先想到是排序,那么时间复杂度自然就是O(NlgN).那么使用二叉堆如何解决呢? 对于下面一个数组,共有12个元素,我们的目标就是找出第5大元素——12 首先建立一个具有M个元素的最小堆, ...