文档章节

scala反射生成实例

lost_o0
 lost_o0
发布于 2015/03/02 10:26
字数 650
阅读 1618
收藏 0

akka实现的通过反射获取类或生成实例(包含生成`object`实例),但是不能生成抽象类的实例!(这也是为什么继承Actor的业务逻辑类不能是抽象的!)

这些代码可直接摘出来用。

/**
 * Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
 */
package akka.actor

import scala.collection.immutable
import java.lang.reflect.InvocationTargetException
import scala.reflect.ClassTag
import scala.util.Try

/**
 * The DynamicAccess implementation is the class which is used for
 * loading all configurable parts of an actor system (the
 * [[akka.actor.ReflectiveDynamicAccess]] is the default implementation).
 *
 * This is an internal facility and users are not expected to encounter it
 * unless they are extending Akka in ways which go beyond simple Extensions.
 * //这些东西摘出来用嘛。
 */
abstract class DynamicAccess {
  /**
   * Convenience method which given a `Class[_]` object and a constructor description
   * will create a new instance of that class.
   *
   * {{{
   * val obj = DynamicAccess.createInstanceFor(clazz, Seq(classOf[Config] -> config, classOf[String] -> name))
   * }}}
   */
  def createInstanceFor[T: ClassTag](clazz: Class[_], args: immutable.Seq[(Class[_], AnyRef)]): Try[T]

  /**
   * Obtain a `Class[_]` object loaded with the right class loader (i.e. the one
   * returned by `classLoader`).
   */
  def getClassFor[T: ClassTag](fqcn: String): Try[Class[_ <: T]]

  /**
   * Obtain an object conforming to the type T, which is expected to be
   * instantiated from a class designated by the fully-qualified class name
   * given, where the constructor is selected and invoked according to the
   * `args` argument. The exact usage of args depends on which type is requested,
   * see the relevant requesting code for details.
   */
  def createInstanceFor[T: ClassTag](fqcn: String, args: immutable.Seq[(Class[_], AnyRef)]): Try[T]

  /**
   * Obtain the Scala “object” instance for the given fully-qualified class name, if there is one.
   */
  def getObjectFor[T: ClassTag](fqcn: String): Try[T]

  /**
   * This is the class loader to be used in those special cases where the
   * other factory method are not applicable (e.g. when constructing a ClassLoaderBinaryInputStream).
   */
  def classLoader: ClassLoader
}

/**
 * This is the default [[akka.actor.DynamicAccess]] implementation used by [[akka.actor.ExtendedActorSystem]]
 * unless overridden. It uses reflection to turn fully-qualified class names into `Class[_]` objects
 * and creates instances from there using `getDeclaredConstructor()` and invoking that. The class loader
 * to be used for all this is determined by the actor system’s class loader by default.
 */
class ReflectiveDynamicAccess(val classLoader: ClassLoader) extends DynamicAccess {

  override def getClassFor[T: ClassTag](fqcn: String): Try[Class[_ <: T]] =
    Try[Class[_ <: T]]({
      val c = Class.forName(fqcn, false, classLoader).asInstanceOf[Class[_ <: T]]
      val t = implicitly[ClassTag[T]].runtimeClass
      if (t.isAssignableFrom(c)) c else throw new ClassCastException(t + " is not assignable from " + c)
    })

  override def createInstanceFor[T: ClassTag](clazz: Class[_], args: immutable.Seq[(Class[_], AnyRef)]): Try[T] =
    Try {
      val types = args.map(_._1).toArray
      val values = args.map(_._2).toArray
      val constructor = clazz.getDeclaredConstructor(types: _*)
      constructor.setAccessible(true)
      val obj = constructor.newInstance(values: _*)
      val t = implicitly[ClassTag[T]].runtimeClass
      if (t.isInstance(obj)) obj.asInstanceOf[T] else throw new ClassCastException(clazz.getName + " is not a subtype of " + t)
    } recover { case i: InvocationTargetException if i.getTargetException ne null ⇒ throw i.getTargetException }

  override def createInstanceFor[T: ClassTag](fqcn: String, args: immutable.Seq[(Class[_], AnyRef)]): Try[T] =
    getClassFor(fqcn) flatMap { c ⇒ createInstanceFor(c, args) }

  override def getObjectFor[T: ClassTag](fqcn: String): Try[T] = {
    val classTry =
      if (fqcn.endsWith("$")) getClassFor(fqcn)//object命名规则
      else getClassFor(fqcn + "$") recoverWith { case _ ⇒ getClassFor(fqcn) }
    classTry flatMap { c ⇒
      Try {
        val module = c.getDeclaredField("MODULE$")//通过获得变量"MODULE$"来初始化
        module.setAccessible(true)
        val t = implicitly[ClassTag[T]].runtimeClass
        module.get(null) match {
          case null                  ⇒ throw new NullPointerException
          case x if !t.isInstance(x) ⇒ throw new ClassCastException(fqcn + " is not a subtype of " + t)
          case x: T                  ⇒ x
        }
      } recover { case i: InvocationTargetException if i.getTargetException ne null ⇒ throw i.getTargetException }
    }
  }
}


© 著作权归作者所有

共有 人打赏支持
lost_o0
粉丝 10
博文 37
码字总数 31139
作品 0
烟台
scala object类与普通class的区别与联系

原讨论:http://stackoverflow.com/questions/1755345/scala-difference-between-object-and-class class是定义是描述。它依照方法、或者其他组成元素定义一个类型。 object是单例。它是你所...

柴火
2014/09/02
0
0
Shapeless入门指南(一):自动派生 typeclass 实例

本文由 Jilen 发表在 ScalaCool 团队博客。 shapeless 是一个类型相关的库,提供了很多有趣的功能。 本文介绍其中一个重要功能:自动派生 typeclass 实例。 Hlist Shapeless 实现了 ,不同于...

ScalaCool
2017/09/15
0
0
Scala之TypeTags and Manifests

注:本文为译文,原文是Scala官方文档中的一篇,这里翻译出来作为本系列的一篇文章。原文链接: http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html。 本文原文出处:...

bluishglc
2016/09/20
0
0
Scala "Hello,world!" 程序

"Hello, world!" 程序 首先我们使用标准的 “Hello, world!” 程序来演示一下 Scala 的简单使用 这个程序的结构对于 Java 程序员来说应该比较熟悉: 程序由 main 方法组成, 它使用命令行参数即...

JackieYeah
2016/06/25
587
0
【Scala】Cake模式和依赖注入

依赖注入(Dependency Injection)和控制反转(Inversion of Control) Dependency Injection & Inversion of Control是Martin Fowler在2004年所提出來的一个概念,Martin Fowler在这篇文章中...

JasonDing
2016/03/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

帧动画(wifi信号动态动画)

准备六张wifi不同信号强度的素材图片,复制到drawable目录中 在drawable目录中新建frame文件,并编写代码 <animation-list xmlns:android="http://schemas.android.com/apk/res/android"> ...

lanyu96
23分钟前
1
0
快速get到学习Linux操作系统的点

Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。Linux能够运行主要的UNIX工具软件、网络协议和应用程序。它支持32位...

问题终结者
31分钟前
1
0
Django2 model操作数据库

1.将应用(如learn)添加到安装应用配置中 将我们新建的应用(learn)添加到 settings.py 中的 INSTALLED_APPS中,告诉Django有这么一个应用。 INSTALLED_APPS = [ 'django.contrib.ad...

MichaelShu
34分钟前
1
0
SpringBoot基础篇Bean之条件注入之注解使用

更多Spring文章,欢迎点击 一灰灰Blog-Spring专题 bean的条件注入,除了前面一篇博文中介绍的通过@Conditional注解配合Condition接口的实现之外,还提供了更多简化的注解使用方式,省略了自己...

小灰灰Blog
45分钟前
1
0
git clone 报错 Clone failed: Authentication failed for

新装了系统,git和phpstorm的配置全都没有了,重新安装了git和phpstorm 系统:windows10 代码托管平台:阿里云code 软件的安装不作赘述。 报错1 Could not read from remote repository 解决...

Marhal
46分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部