我知道有很多文章解释了如何在Java EE中使用CDI,但我无法弄清楚它实际带来了什么优势.例如,假设我有一个当前使用Foo实例的类.我也许会这样做
Foo myFoo = new Foo();
Run Code Online (Sandbox Code Playgroud)
要么
// Better, FooFactory might return a mock object for testing
Foo myFoo = FooFactory.getFoo();
Run Code Online (Sandbox Code Playgroud)
我一直在读CDI,我可以这样做:
@Inject
Foo myFoo;
Run Code Online (Sandbox Code Playgroud)
但为什么这比以前的工厂方法更好?我假设还有一些其他用例,我不知道,但我无法识别这一点.
如果我理解了下面的响应,那么概念就是DI框架充当集中配置的主对象工厂.这是一个合理的解释吗?
更新
我从那时起开始学习Spring,现在这更有意义了.下面的段落取自Spring in Practice,以一个AccountService类为例,该类反过来使用了一个实例AccountDao.我为长篇报道道歉,但我认为它真正解释了为什么注入资源提供了超过标准初始化的东西.
您可以使用new关键字构造AccountService,但是服务层对象的创建很少是如此简单.它们通常依赖于DAO,邮件发件人,SOAP代理等等.您可以在AccountService构造函数中(或通过静态初始化)以编程方式实例化每个依赖项,但这会导致硬件依赖性和级联更改,因为它们已被换出.
此外,您可以在外部创建依赖项,并通过setter方法或构造函数参数在AccountService上设置它们.这样做可以消除硬内部依赖关系(只要它们通过接口在AccountService中声明),但是你到处都有重复的初始化代码.以下是如何创建DAO并以Spring方式将其连接到AccountService:
<bean id="accountDao" class="com.springinpractice.ch01.dao.jdbc.JdbcAccountDao"/>
<bean id="accountService"
class="com.springinpractice.ch01.service.AccountService">
<property name="accountDao" ref="accountDao"/>
</bean>
Run Code Online (Sandbox Code Playgroud)
如上所述配置bean后,您的程序现在可以AccountService从Spring ApplicationContext 请求一个实例,Spring DI框架将实例化需要实例化的所有内容.
让我们想象一下,我想在表格中显示一个库存项目列表(使用Java).域模型由一个抽象基类StockItem组成,其中包含各种其他类型的库存项.StockItem提供了一个最小的接口(getId()和getDescription())但除此之外,子类可能有很大的变化.
如果我将自己限制在StockItem上定义的方法,我将无法向用户提供足够的详细信息,因此这意味着某些列将引用不适用于某些行的字段(例如,实物商品是可数的,该计数应出现在表中,而预计也出现在表中的服务项目是不可数的,在这种情况下应显示"N/A"或类似情况.
为了坚持"可数"的例子,在我看来有几个解决方案(但请记住,Countable不会是唯一涉及的接口).
使可数接口成为基类的一部分,并强制所有内容都是可数的,即使它们不是.没有意义的类需要返回一些特殊值或抛出异常或以其他方式表明它们违反了StockItem的合同.
在我的迭代器中,使用大量的instanceof检查并适当地进行转换.如果我引入StockItem的新子类或以其他方式更改继承树,我将不得不记得更改此代码.
这两个看起来像对我的反模式,我有兴趣听到可能采取的任何更多的优雅方法.我怀疑这没有灵丹妙药,但如果其他语言具有使这种类型的东西更容易的功能,我也有兴趣听到它们(虽然只是出于普遍的兴趣,我不会在任何时候重新实现这个系统不久:)
谢谢,菲尔
我正在尝试找到一种方法来明确指定部署到Glassfish 3.1.2.2的Web应用程序的上下文路径,但到目前为止我还没有运气.任何人都可以就此提供指导吗?背景如下:
我有一个Web应用程序,包含两个独立的Netbeans(7.0)项目.第一个是Web服务,称为FooWS.第二个是面向用户的Web应用程序,它使用FooWS Web服务.它叫做FooApp.
我最近将glassfish升级到3.1.2.2以期解决其他问题,现在当我部署FooWS应用程序时,它成功部署但使用上下文路径/ web而不是/ FooWS.这不是我特别关心的事情,除了当我尝试部署FooApp时,glassfish还尝试将其部署到/ web导致以下错误:
严重:加载应用程序时出现异常:java.lang.Exception:WEB0113:虚拟服务器[服务器]已经在[/ web]上加载了一个Web模块[FooWS]; 因此,无法在此虚拟服务器上的此上下文路径中加载Web模块[FooApp].
FooApp的web.xml如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>defaultWebRootId</param-name>
<param-value>2631</param-value>
</context-param>
<listener>
<listener-class>com.foo.service.AppInitialiser</listener-class>
</listener>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
Run Code Online (Sandbox Code Playgroud)
FooWS的配置类似.两者都没有提到应用程序上下文,所以我的期望是它应该使用/ FooWS而不是默认的/ web.
显而易见的解决方案似乎是覆盖web.xml中的上下文路径,但我无法找到任何方法.有什么建议?
只是一些跟进,我不小心改变了/ FooW的上下文路径.这次它按预期部署到/ FooW.如果/ FooWS导致旧行为返回,则更改它,也就是说,它再次部署到/ web.好像我现在有一个解决方法.
为了此后任何人的利益,我在3.1.2中获得了相同的行为.我现在已经返回到3.1(b43)并且它的行为符合预期.
我在JavaFX中创建了一个带有单个子组件(按钮)的TitledPane,如下所示:
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TitledPane animated="false" layoutX="137.0" layoutY="60.0" prefHeight="400.0" prefWidth="600.0" text="untitled" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" >
<children >
<Button layoutX="193.1875" layoutY="133.5" mnemonicParsing="false" prefHeight="374.0" prefWidth="598.0" text="Button" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</content>
</TitledPane>
</children>
</AnchorPane>
Run Code Online (Sandbox Code Playgroud)
如下所示.按钮周围有相当多的间距,我想将其减少到0或者可能是单个像素.我没有看到任何可以执行此操作的AnchorPane或TitledPane的属性.有这样的财产吗?

我有一个桌面Java/Swing应用程序,它通过Java Webstart部署(客户端在XP上使用Java 6u20).我收到了申请暂停用户的间歇性报告.我设法在挂起期间登录到这样的系统,发现没有绘制UI(就像EDT被阻止一样).
我用jstack列出了线程; 我没有看到任何关于输出的死锁的提及,因为我对jstack很新,我不确定我还应该寻找什么.
我必须编辑堆栈跟踪以使其适合stackoverflow限制,希望没有遗漏任何重要意义.
谢谢,
菲尔
Full thread dump Java HotSpot(TM) Client VM (16.3-b01 mixed mode, sharing):
"AWT-EventQueue-0" prio=6 tid=0x03e3f000 nid=0xe44 in Object.wait() [0x0516f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at java.awt.EventQueue.getNextEvent(Unknown Source)
- locked <0x1d4b91d8> (a java.awt.EventQueue)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
<SNIP>
Locked ownable synchronizers:
- None
"ServerThread" prio=6 tid=0x058f7c00 nid=0xa08 waiting for monitor entry [0x055be000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.sun.deploy.security.CPCallbackHandler$ParentCallback.check(Unknown Source)
- waiting to lock <0x1d485f80> (a com.sun.deploy.security.CPCallbackHandler$ParentCallback)
at com.sun.deploy.security.CPCallbackHandler$ParentCallback.access$1400(Unknown Source) …Run Code Online (Sandbox Code Playgroud) 我有一个通过Java Webstart启动的Java应用程序。有时,在重新部署应用程序之后,启动该应用程序会导致每次启动都将其下载两次。我还没有深入了解这个问题,但我认为它可能与我们的鱿鱼代理有关,后者似乎与Java交互不良。为了进一步研究这个问题,我想了解一下javaws在做什么。javaws是否有可用的此类选项?
只是一个小小的更新,如果将Java配置为显示控制台,则在将焦点放在控制台上时单击“ 5”会将日志记录级别设置为5,这是最详细的日志记录级别。这可能很有用,但不能解决应用程序无法做到这一点的情况。
我有一个Swing应用程序的问题,由于我目前无法识别的原因,有时会通过文本输入字段获得焦点.我怀疑某种竞争条件,但我无法看到导致焦点事件的原因.
该字段附加了一个焦点监听器,因此可以直接向focusGained()事件处理程序添加断点.当我这样做时,我可以看到底层事件,而该事件又包含一个CausedFocusEvent.Cause实例.名称字段设置为"ACTIVATION".
查看堆栈跟踪,我可以看到以下内容:
Thread [AWT-EventQueue-0] (Suspended (breakpoint at line 174 in MyPanel$3))
MyPanel$3.focusGained(FocusEvent) line: 174
AWTEventMulticaster.focusGained(FocusEvent) line: not available
InputField(Component).processFocusEvent(FocusEvent) line: not available
InputField(Component).processEvent(AWTEvent) line: not available
InputField(Container).processEvent(AWTEvent) line: not available
InputField(Component).dispatchEventImpl(AWTEvent) line: not available
InputField(Container).dispatchEventImpl(AWTEvent) line: not available
InputField(Component).dispatchEvent(AWTEvent) line: not available
DefaultKeyboardFocusManager(KeyboardFocusManager).redispatchEvent(Component, AWTEvent) line: not available
DefaultKeyboardFocusManager.typeAheadAssertions(Component, AWTEvent) line: not available
DefaultKeyboardFocusManager.dispatchEvent(AWTEvent) line: not available
InputField(Component).dispatchEventImpl(AWTEvent) line: not available
InputField(Container).dispatchEventImpl(AWTEvent) line: not available
InputField(Component).dispatchEvent(AWTEvent) line: not available
SunToolkit$1.run() line: not available
PeerEvent(InvocationEvent).dispatch() line: not available
EventQueue.dispatchEventImpl(AWTEvent, Object) line: …Run Code Online (Sandbox Code Playgroud) 我正在使用Dojo 1.8创建一个折线图,我用它绘制时间序列数据.数据包括24个周期内每5分钟采集的样本,最多可提供288(12x24)个数据点.
为了在图表上有工具提示,我需要在图表上启用标记(dojo需要这个).问题是默认情况下,dojo会为每个数据点创建一个标记,这会导致标记太多.理想情况下,我会显示最新数据点的单个标记,也可能每隔一两小时显示一次标记.
可以自定义标记的外观,但到目前为止,我还没有找到任何方法来自定义标记出现的频率.任何建议都会非常受欢迎.
我有以下 AspectJ 示例,我已经将其作为“hello world”风格的概念证明。StyleAspect尽管实际代码SomeClass只执行一次(根据需要),但 中的建议代码似乎执行了两次。
这是代码:
首先是一个名为 WithStyle 的注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface WithStyle {
}
Run Code Online (Sandbox Code Playgroud)
然后,拦截任何带有@WithStyle 注释的代码的切面
@Aspect
public class StyleAspect {
@Around("@annotation(WithStyle)")
public Object doItWithStyle(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("Doing it in style...");
Object result = pjp.proceed();
System.out.println("Done");
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
最后,一些带有注释的代码
public class SomeClass {
@WithStyle
public void doIt() {
System.out.println("I'm doing it....");
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行它时,我得到以下输出:
--- exec-maven-plugin:1.2.1:exec (default-cli) @ AspectJTest ---
Doing it in style...
Doing it in style...
I'm doing …Run Code Online (Sandbox Code Playgroud) 例如,我有一些DAO类形式的现有Java代码
class EmployeeDao {
public EmployeeDao(Connection conn) {
// Prepare statements to be used by the methods below
}
public Employee getEmployeeById(long id) {
}
public Collection<Employee> getEmployeesByDepartment(long departmentId) {
}
...
}
Run Code Online (Sandbox Code Playgroud)
所有DAO类都使用JDBC连接构造.构造函数准备方法所需的任何语句.这在单线程环境(例如批处理)中工作正常,其中调用者可以创建连接并使用该连接实例化所需的Dao对象.
我希望能够在Java Web应用程序中使用它,但我只是不确定如何处理JDBC连接.以下是一些想法:
每个请求都会创建一个新的JDBC连接并实例化所需的Dao对象.从连接创建和Dao实例化中显然都很昂贵
每个请求从JNDI数据源获取连接并实例化所需的Dao对象.这消除了连接创建的开销,但保留了准备所有语句的开销
每个请求从JDNI数据源获取连接并实例化所需的Dao对象,但构造函数不再准备语句,它们是根据需要延迟准备的.
HttpSessionListener实例化Dao对象并将它们存储在会话中(使用setAttribute).会话到期时,连接将关闭.
创建无状态会话bean.bean将实例化所需的Dao对象.
选项1不是真正的竞争者,只是在那里展示我的思考过程.
选项2和3可以工作,但似乎是次优的,不得不在每个请求上准备语句似乎是一个容易避免的开销,但我想我错过了
选项4避免了在每次调用时准备语句的开销,但代价是手动维护状态.我不认为这是Servlet/JSP应用程序中的预期使用模式(保持连接一段时间).
选项5应该工作但似乎需要很多开销,这意味着我需要一个完整的EJB容器而不是一个简单的servlet引擎.
对于考虑到以下目标的人们采用了哪些方法:
PS:我知道像Hibernate和Entity Beans这样的框架可以抽象出一些这样的东西,但是我想要解决"无框架"基础案例.
我对IE8有一个非常奇怪的问题; 我已经尽可能地减少了以下摘录:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript">
function dismissOperation() {
alert("Would dismiss");
}
</script>
</head>
<body >
<input type="text" />
<input type="text" onfocus="alert('text box got focus')" />
<button onclick="dismissOperation()" onfocus="alert('Dismiss button got focus')">Dismiss</button>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
问题是,当一个值输入到第一个文本框中,然后返回/输入时,该按钮将获得焦点并传递click事件(在按钮上).
作为测试,我添加了第二个文本输入框(如上所示).添加第二个框后,当在第一个框中输入值时,焦点仍会直接转到按钮.
是什么导致焦点转到按钮并发出点击?这有什么解决方法吗?