Grails 在bootstrap中使用groovy元类模拟Shiro SecurityUtils

Grails 在bootstrap中使用groovy元类模拟Shiro SecurityUtils,grails,groovy,metaprogramming,shiro,bootstrapping,Grails,Groovy,Metaprogramming,Shiro,Bootstrapping,有关更多背景信息,请参阅 我试图在BootStrap.groovy中模拟Shiro SecurityUtils.getSubject()方法。我决定采用这种方法是因为最新Shiro版本中的主题生成器在当前版本的灵活插件(我正在使用)中不可用。我决定尝试使用SecurityUtils.metaClass,但我有一种感觉,我遗漏了一些关于元类如何工作的非常基本的东西。作为参考,以下是我的可跟踪类: abstract class Trackable { User createdB

有关更多背景信息,请参阅

我试图在BootStrap.groovy中模拟Shiro SecurityUtils.getSubject()方法。我决定采用这种方法是因为最新Shiro版本中的主题生成器在当前版本的灵活插件(我正在使用)中不可用。我决定尝试使用SecurityUtils.metaClass,但我有一种感觉,我遗漏了一些关于元类如何工作的非常基本的东西。作为参考,以下是我的可跟踪类:

    abstract class Trackable {
       User createdBy
       Date dateCreated
       User lastUpdatedBy
       Date lastUpdated

       static constraints = {
           lastUpdated(nullable:true)
           lastUpdatedBy(nullable:true)
           createdBy(nullable:true)
       }

       def beforeInsert = {
           def subject

           try {
               subject = SecurityUtils.subject
           } catch (Exception e) {
               log.error "Error obtaining the subject.  Message is [${e.message}]"
           }

           createdBy = (subject ? User.get( subject.principal ) :
User.findByUsername("admin"))
       }

       def beforeUpdate = {
           def subject

           try {
               subject = SecurityUtils.subject
           } catch (Exception e) {
               log.error "Error obtaining the subject.  Message is [${e.message}]"
           }

           lastUpdatedBy = (subject ? User.get( subject.principal ) :
User.findByUsername("admin"))
       }
   }
在我的BootStrap.groovy中,我有:

   def suMetaClass = new ExpandoMetaClass(SecurityUtils)

   suMetaClass.'static'.getSubject = {[getPrincipal:{2}, toString:{"Canned Subject"}] as Subject}

   suMetaClass.initialize()

   SecurityUtils.metaClass = suMetaClass
这就行了。。。某种程度上。如果我从BootStrap.groovy打印出主题,我会得到“罐头主题”。如果我尝试创建并保存Trackable子类的实例,我会得到:


我是否遗漏了元类如何工作的一些完整信息?

我知道发生了什么。在我的引导过程中,我做了如下工作:

def init = { servletContext->
  switch (Environment.current.name) {
    case "local":
      def suMetaClass = new ExpandoMetaClass(SecurityUtils)
      suMetaClass.'static'.getSubject = {[getPrincipal:{2}, toString:{"Canned Subject"}] as Subject}
      suMetaClass.initialize()
      SecurityUtils.metaClass = suMetaClass

      new TrackableSubClass().save()

      //Create some other domain instances

      SecurityUtils.metaClass = null
  }
  //Create a couple domain instances that aren't environment specific
}
我添加了一些调试语句,发现我看到的错误发生在init闭包的末尾。我在谷歌上搜索了一下,再次检查了如何刷新我的休眠会话。然后我做了以下更改:

def sessionFactory

def init = { servletContext->
  switch (Environment.current.name) {
    case "local":
      def suMetaClass = new ExpandoMetaClass(SecurityUtils)
      suMetaClass.'static'.getSubject = {[getPrincipal:{2}, toString:{"Canned Subject"}] as Subject}
      suMetaClass.initialize()
      SecurityUtils.metaClass = suMetaClass

      new TrackableSubClass().save()

      //Create some other domain instances

      sessionFactory.currentSession.flush()

      SecurityUtils.metaClass = null
  }
  //Create a couple domain instances that aren't environment specific
}

这似乎已经完全解决了这个问题,现在我应该能够从Trackable中删除繁琐的try/catch块了。:-)

我想知道这是否与Grails1.1.1在Groovy1.6.3上相关?
def sessionFactory

def init = { servletContext->
  switch (Environment.current.name) {
    case "local":
      def suMetaClass = new ExpandoMetaClass(SecurityUtils)
      suMetaClass.'static'.getSubject = {[getPrincipal:{2}, toString:{"Canned Subject"}] as Subject}
      suMetaClass.initialize()
      SecurityUtils.metaClass = suMetaClass

      new TrackableSubClass().save()

      //Create some other domain instances

      sessionFactory.currentSession.flush()

      SecurityUtils.metaClass = null
  }
  //Create a couple domain instances that aren't environment specific
}