Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring范围代理模式AspectJ?_Java_Spring_Scope_Aop - Fatal编程技术网

Java Spring范围代理模式AspectJ?

Java Spring范围代理模式AspectJ?,java,spring,scope,aop,Java,Spring,Scope,Aop,我想实现一些功能来获取当前登录用户,即代表当前登录用户的JPA实体。但不是用传统的方式 CurrentUserService.getCurrentUser(){load the user from db by login}) 我想用更CDI的方式来做 我想要一个CurrentUserFactory,它将当前用户作为请求范围的bean提供给一个自定义限定符currentbean 限定符: @Target({ ElementType.FIELD, ElementType.METHOD, Elem

我想实现一些功能来获取当前登录用户,即代表当前登录用户的JPA实体。但不是用传统的方式

CurrentUserService.getCurrentUser(){load the user from db by login}) 
我想用更CDI的方式来做

我想要一个CurrentUserFactory,它将当前用户作为请求范围的bean提供给一个自定义限定符currentbean

限定符:

@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface CurrentUser {
}
工厂:

@Component
public class CurrentUserFactory {

  @CurrentUser
  @Bean
  @Scope(value = WebApplicationContext.SCOPE_REQUEST,
         proxyMode = ScopedProxyMode.TARGET_CLASS)
  public User currentUser() throws IllegalStateException {
      return
          <DoWhatIMean>
             User load form DB by:
             SecurityContextHolder.getContext().getAuthentication().getName()
          </dwim>
}
那很好

但是,如果我使用当前用户直接进行JPA Hibernate操作,比如通过引用currentUser搜索实体,或者通过引用currentUser存储实体,那么它就会失败,没有真正有用的例外情况。-这是显而易见的

原因是spring在currentUser中注入了一个CGI代理。只要只使用此代理的属性,这就可以正常工作,但如果开始使用引用本身,则会失败

我知道我在规范的边缘工作,如果我的想法不起作用,我接受。但我想问你,我有个办法让它工作。这样开发人员就可以像普通JPA加载的实体一样使用这个currentUser对象

我想要的至少是当前用户的这种非常简单的用法:

@Resouce
@CurrenctUser
User currentUser;
就这样

可能有人有办法让它工作,例如我正在使用编译时AspectJ的AspectJ技巧

无论如何:正如我之前说过的,异常不是我的问题,我理解它们,因为它们只是所描述问题的指标

尝试按currentUser加载时出现异常,请从书签b中选择b,其中user=

java.lang.IllegalStateException:org.hibernate.TransientObject异常:对象引用未保存的临时实例-在刷新之前保存临时实例:domain.User

尝试保存书签时出现异常书签具有字段用户

无法插入:[域.书签];SQL[插入书签businessId、引用文件夹、标题、用户值?、?、?、?];约束[null];嵌套异常为org.hibernate.exception.ConstraintViolationException:无法插入:[domain.Bookmark]


Spring代理由ScopedProxyFactoryBean创建。它的文档说明代理实现了“ScopedObject”,它允许您访问原始bean

@Resource
@CurrentUser
private User currentUser;

public static <T> T unwrapScopedProxy(T maybeProxy) {
    if (maybeProxy instanceof ScopedObject) {
        return (T) ((ScopedObject) maybeProxy).getTargetObject();
    } else {
        return maybeProxy;
    }
}

...
query.setParameter("user", unwrapScopedProxy(currentUser));

了解例外情况会有帮助。@matt b:我已经添加了例外情况。在获取用户对象和从书签b中选择b(其中User=)之间的任意位置是否修改了用户对象?询问?@mattb:不,不是。但问题是,@Ressource@CurrentUser CurrentUser是一个Spring代理,因为它的工厂方法是Scopevalue=WebApplicationContext.SCOPE\u REQUEST。感谢您对ScopedProxyFactoryBean和ScopedObject的参考,以及如何展开的提示。无论如何,这并不能解决问题。我想要的至少是当前用户的简单使用。。。你建议的是一个客户端解决方案程序员如何使用这种风格需要在他使用当前用户的每一点上注意正确的处理,我需要的是一个用户如何使用当前用户不必注意的解决方案。只有提供当前用户的程序员才可以做这些额外的基础设施工作。我明白了,所以你基本上反对客户端不知道@Resource是如何实现的。这是有效的,令人钦佩的是,您没有为了方便而牺牲架构的纯洁性。如果您制作一个通用API呢?公共接口ICurrentUserHolder{User getCurrentUser;}以某种方式,您必须打开代理;您可以将展开隐藏在接口后面,但它仍然必须完成。您没有说明如何构造查询,但另一个选项是创建一个Spring查询包装器,自动展开传递给setParameter的任何Spring代理。Spring查询包装器?-听起来很有趣。这是春天的官方概念吗?你能给我一些我可以开始的链接吗?不,不是官方的。我想象的是一个由查询工厂返回的定制代理,不管它是什么。
@Resource
@CurrentUser
private User currentUser;

public static <T> T unwrapScopedProxy(T maybeProxy) {
    if (maybeProxy instanceof ScopedObject) {
        return (T) ((ScopedObject) maybeProxy).getTargetObject();
    } else {
        return maybeProxy;
    }
}

...
query.setParameter("user", unwrapScopedProxy(currentUser));