专栏首页java达人Spring aop 的代理机制

Spring aop 的代理机制

Spring aop 是通过代理实现的,代理有静态代理,jdk动态代理和cglib动态代理,代理就像我们生活中的房产中介,你不直接与房主,银行接触,而是通过中介与他们沟通联系。

代理的结构如图所示:

RealSubject 和 Proxy都实现了相同的接口Subject,Proxy持有RealSubject的引用,但Client 调用 request方法时,Proxy将请求转发给RealSubject,其中可以添加各种访问控制。

但是静态代理有一个弊端,需要为每一个目标类创建一个代理类,如果需要代理的对象很多的话,就得编写相应的代理类,于是jdk动态代理出现了,它主要用了 java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。

我们先实现java.lang.reflect.InvocationHandler,添加需要的横切逻辑

public class AccessControl implements InvocationHandler {

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

//调用前的处理

  System.out.println("调用前验证");

  Object obj  = method.invoke(proxy, args);

//调用后的处理

  System.out.println("调用后处理");

  return obj;

}

}

然后通过Proxy为不同的类型生成相应的代理对象。

Proxy.newProxyInstance(targertClass1.getClassLoader(), targertClass1.getInterfaces(),accessControl);

Proxy.newProxyInstance(targertClass2.getClassLoader(), targertClass2.getInterfaces(),accessControl);

不管targetClass有多少类型,都可以通过Proxy生成具有相同访问控制accesControl的代理对象。

从上面示例可知jdk动态代理需要被代理类实现接口(Interface),对于没有实现任何接口的目标对象,我们就要另找方法了。默认情况下,当Spring发现目标对象没有实现任何接口时,会使用CGLIB,为目标对象动态生成代理对象,其实质就是对目标对象进行继承,生成子类,子类覆盖父类的方法,在其中加入额外的访问控制,不过如果类中的方法声明为final的话,就不能对它进行扩展。

Spring 创建代理的秘密在DefaultAopProxyFactory 类中可以找到:

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()) {

    return new JdkDynamicAopProxy(config);

  }

  return CglibProxyFactory.createCglibProxy(config);

  } else {

  return new JdkDynamicAopProxy(config);

  }

}

如果isOptimize()返回true,或者proxyTargetClass属性为true,或者目标对象没有接口实现,就采用cglib动态代理,否则就用jdk动态代理。再看看JdkDynamicAopProxy中的getProxy

public Object getProxy(ClassLoader classLoader) {

  if (logger.isDebugEnabled()) {

      logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());

  }

  Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);

  findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);

  return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

}

请看最后一行代码,是否有似曾相识之感。

Spring aop 仅作用于方法,如果你想对构造方法或字段作拦截处理,就要引入AspectJ,它支持在编译期间织入横切逻辑,提高运行期间的性能,但在易用性和灵活性上不如Spring aop。值得注意的是,Spring中@AspectJ注解区别的切面也是基于Spring aop 的代理机制实现的,不要被这个名称混淆了。

java达人

ID:drjava

(长按或扫码识别)

本文分享自微信公众号 - java达人(drjava),作者:java达人

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-10-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Spring aop 的代理机制

    Spring aop 是通过代理实现的,代理有静态代理,jdk动态代理和cglib动态代理,代理就像我们生活中的房产中介,你不直接与房主,银行接触,而是通过中介...

    java达人
  • 网络攻击是如何运作的—一份完整的列表 ( 1 )

    作者:PAUL CUCU 译者:java达人 来源:https://heimdalsecurity.com/blog/cyber-attack/ 你一定在新闻...

    java达人
  • 与我一起学习微服务架构设计模式12—部署微服务应用

    首先要安装运行时,将程序发布包复制到计算机并启动服务。对于java,每个服务实例作为JVM进程运行。

    java达人
  • Spring aop 的代理机制

    Spring aop 是通过代理实现的,代理有静态代理,jdk动态代理和cglib动态代理,代理就像我们生活中的房产中介,你不直接与房主,银行接触,而是通过中介...

    java达人
  • 支付宝二维码脱机认证库测试(linux_x86平台验证)

    最近在调试支付宝给提供的二维码脱机认证库,他们给提供了几个文档和 libposoffline.so库文件。

    特立独行的猫a
  • 为什么SDN的部署迟迟提不上日程?

    随着外界对软件定义网络(SDN)前景的大肆宣传,我们看到许多大型运营商已经开始认真探索基于SDN的解决方案。一些公司已经开始将他们的网络转变为基于集中式软件控制...

    SDNLAB
  • 分享一套内容信息管理系统(CMS源码版)

    内容管理系统是一种位于WEB前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容管理解决方案重点解决各种非结构化或半结构化的数字资源...

    程序源代码
  • Redis基础你掌握多少了?来查漏补缺?

    Redis 是开源的内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。它支持多种类型的数据结构,如 字符串strings, 散列 hashes, 列...

    猿哥
  • Redis基础你掌握多少了?来查漏补缺?

    Redis 是开源的内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。它支持多种类型的数据结构,如 字符串strings, 散列 hashes, 列...

    用户3578099
  • 【机器学习】机器学习正在五个方面重塑我们的世界

    机器学习的技术越来越成熟,与大数据结合在一起为我们的世界带来了巨大的变化。对此,大数据专家Bernard Marr总结了机器学习在听、说、读、写、看五个方面如何...

    陆勤_数据人网

扫码关注云+社区

领取腾讯云代金券