java 为什么 Spring 的 @Configurable 有时有效,有时无效?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/828747/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 13:57:12  来源:igfitidea点击:

Why does Spring's @Configurable sometimes work and sometimes not?

javaspringjpadependency-injectionannotations

提问by Robert Campbell

I'm trying to use automatic dependency injection via Spring's @Configurable annotation w/ @Resource on the fields needing injection. This involved some setup, like passing spring-agent.jar to my JVM. For the full details see here.

我正在尝试通过 Spring 的 @Configurable 注释和 @Resource 在需要注入的字段上使用自动依赖注入。这涉及一些设置,比如将 spring-agent.jar 传递给我的 JVM。有关完整的详细信息,请参见此处

It works... mostly. When my Tomcat is booting up, I see the AspectJ init messages, my User objects automatically get FileService references, etc.

它有效......主要是。当我的 Tomcat 启动时,我看到 AspectJ 初始化消息,我的用户对象自动获取 FileService 引用等。

The problem is that sometimes it just doesn't happen. It appears to be completely random; sometimes I boot up and the dependencies are not injected, sometimes they are. I previously had trouble with @Transactional being on my User because it created a conflict, I believe with proxies. I am using JPA, so my User is marked with @Entity, so my best guess right now is that this is creating a conflict. I've read you can't auto proxy a proxy. To offset the conflict, I followed some notes I found online about excluding CGLIBand javassistwhich Hibernate (my JPA impl) uses.

问题是有时它不会发生。它似乎是完全随机的;有时我启动并没有注入依赖项,有时它们是。我以前在我的用户上使用 @Transactional 时遇到了麻烦,因为它造成了冲突,我相信是代理。我正在使用 JPA,所以我的用户被标记为 @Entity,所以我现在最好的猜测是这会造成冲突。我读过你不能自动代理代理。为了抵消冲突,我遵循了一些我在网上找到的关于排除Hibernate(我的 JPA impl)使用的CGLIBjavassist 的注释。

Clues:

线索:

  • It's all or nothing. All of my @Configurable instances have been injected or none of them.
  • Reloading (reinstantiating) the Entity from the DB doesn't appear to help; it's either working or not.
  • Rebooting Tomcat any number of time also won't even fix it. The only thing that appears to roll the dice again is a redeploy. In other words, if I redeploy it may work.
  • 要么全有要么全无。我的所有 @Configurable 实例都已注入或没有注入。
  • 从数据库重新加载(重新实例化)实体似乎没有帮助;它要么工作要么不工作。
  • 多次重启 Tomcat 也无法修复它。似乎再次掷骰子的唯一事情是重新部署。换句话说,如果我重新部署它可能会起作用。

How can I figure out what is going wrong? Is anyone using @Configurable with JPA? Why isn't my dependencyCheck = truethrowing an error when dependencies are not actually injected?

我怎样才能弄清楚出了什么问题?有人在 JPA 中使用 @Configurable 吗?当依赖项实际上没有注入时,为什么我的dependencyCheck = true 不抛出错误?

Entity

实体

@Entity
@Configurable(dependencyCheck = true)
@NamedQueries( { @NamedQuery(name = "User.findAll", query = "SELECT user FROM User user"),
    @NamedQuery(name = "User.findByEmail", query = "SELECT user FROM User user WHERE user.email = :email") })
public abstract class User extends BaseModel {

private static final long serialVersionUID = 7881431079061750040L;

@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private Long id;

@Column(unique = true, nullable = false)
private String email;

@Basic(optional = false)
private String password;

@Resource
private transient UserEmailer userEmailer;

@Resource
private transient FileService fileService;

...

aop.xml

文件

<!DOCTYPE aspectj PUBLIC
    "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
    <weaver options="-verbose">
        <include within="com.myapp.domain..*" />
        <exclude within="*..*CGLIB*" />
        <exclude within="*..*javassist*" />
    </weaver>
    <aspects>
        <aspect name="org.springframework.beans.factory.aspectj.AbstractInterfaceDrivenDependencyInjectionAspect" />
    </aspects>
</aspectj>

applicationContext.xml

应用上下文.xml

...

<context:spring-configured />

<context:load-time-weaver />

<context:component-scan base-package="com.myapp" />

...

回答by Thomas Einwaller

First I have to say that it is probably not a good idea to have resources, services or other beans injected into data model classes as dependencies. But that is a question of design.

首先我不得不说,将资源、服务或其他 bean 作为依赖项注入数据模型类可能不是一个好主意。但这是一个设计问题。

To the usage of @Configurable I used it in cases where objects are instantiated from outside the Spring context - like custom tags in web applications, filters or servlets. The first way I tried to use them was by load time weaving like you do. That worked quite well but it had some drawbacks like hot code deployment while debugging did not work anymore.

对于@Configurable 的使用,我在对象从 Spring 上下文外部实例化的情况下使用它 - 例如 Web 应用程序、过滤器或 servlet 中的自定义标签。我尝试使用它们的第一种方法是像您一样通过加载时间编织。这工作得很好,但它有一些缺点,例如热代码部署而调试不再起作用。

I did also experience exactly the problem you describe and so I decided to switch from load time weaving to compile time. Therefor I installed the AJDT pluginin Eclipse and used the aspecjt support of Spring. That solved my problems.

我也确实遇到了您所描述的问题,因此我决定从加载时编织切换到编译时。为此我在 Eclipse 中安装了AJDT 插件并使用了 Spring 的 aspecjt 支持。那解决了我的问题。

回答by jens

To me it sounds like an occurence of a well known bug in Spring: http://jira.springframework.org/browse/SPR-5401.

对我来说,这听起来像是 Spring 中一个众所周知的错误的发生:http: //jira.springframework.org/browse/SPR-5401

Can it be that you are trying to use Configurable in several application contexts? In this case only one of them will be subject to dependency injection. Which one wins depends on which application context is the last one to be loaded.

可能是您尝试在多个应用程序上下文中使用 Configurable 吗?在这种情况下,只有其中一个会受到依赖注入。哪一个获胜取决于哪个应用程序上下文是最后加载的。

Solution? None :-( There are no plans to fix this issue. That is at least what the SpringSource guy told at the JAX conference in Germany in April.

解决方案?无 :-( 目前没有解决这个问题的计划。至少 SpringSource 的人在 4 月份的德国 JAX 会议上是这么说的。

回答by James

Can't spot anything obvious, so just a suggestion - have you tried using compile-time weaving? Hopefully that would lead to consistent results at runtime, although it can be a bit more hassle during development.

找不到任何明显的东西,所以只是一个建议 - 您是否尝试过使用编译时编织?希望这会在运行时产生一致的结果,尽管在开发过程中可能会有点麻烦。

回答by Nathan Feger

It sounds like your deploy process is suspect. Can you do a deployment that works, then copy that off to a directory. Then do another deployment until you get one that doesn't work. (In either order) Then finally, use a tool like beyond compare to compare the two deployment directory structures and files, and see if there are any differences.

听起来您的部署过程很可疑。你能做一个有效的部署,然后把它复制到一个目录中。然后再进行一次部署,直到得到一个不起作用的部署。(顺序不限)然后最后用beyond compare之类的工具比较两个部署目录结构和文件,看看有没有什么不同。

Good luck, nothing like a seemingly random problem to kill some productivity.

祝你好运,没有什么比一个看似随机的问题来杀死一些生产力。

回答by J?rn Zaefferer

When the injection doesn't work, for whatever reason, there is no way for code to do any dependency check, so there is now error thrown.

当注入不起作用时,无论出于何种原因,代码都无法进行任何依赖项检查,因此现在会抛出错误。

Otherwise I can't see anything here that would indicate the random failure. Can you extract a simplified example to check?

否则我在这里看不到任何表明随机失败的东西。你能提取一个简化的例子来检查吗?