我有一个使用JavaFX 2的应用程序,我想确保在接口的每个方法中调用特定的代码:
public interface IControladorDialogoPrincipal extends IControladorDialogo{
@FXML
void abrirCaixa(ActionEvent e);
@FXML
void fecharCaixa(ActionEvent e);
@FXML
void novaPreVenda(ActionEvent evento);
@FXML
void mesclarPreVenda(ActionEvent evento);
}
这是实现上述接口的类的一部分:
public class ControladorDialogoPrincipal extends ControladorDialogoSubmeter implements IProcessamentoListener, IControladorDialogoPrincipal {
@FXML
private StackPane painelPrincipal;
@FXML
private BorderPane painelConteudo;
@FXML
private BorderPane painelProgresso;
@Autowired
private ControladorExecucaoTarefa controladorExecucaoTarefa;
@Autowired
private ControladorDialogoMensagem dialogoMensagem;
@Autowired
private RecuperadorBeanSpring recuperadorBean;
@Override
protected void configurarElementos() {
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
public void handle(WindowEvent e) {
System.exit(0);
}
});
stage.setWidth(800);
stage.setHeight(600);
painelProgresso.toBack();
painelProgresso.setVisible(false);
}
.
.
.
}
所有ControladorDialogo *的基类都是这个抽象类:
public abstract class ControladorDialogo implements IControladorDialogo {
private URL modelo;
protected Stage stage;
protected String titulo = "";
protected List<String> estilos = new ArrayList<String>();
protected Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public final void init() {
try {
stage = new Stage();
definirTitulo(titulo);
stage.setScene(carregarCena());
stage.initModality(Modality.WINDOW_MODAL);
configurarElementos();
} catch (IOException e) {
logger.error("Erro ao tentar carregar arquivo FXML: ", e);
}
}
protected final Scene carregarCena() throws IOException {
Parent root = (Parent) SpringFXMLLoader.load(modelo.openStream(), this);
Scene cena = new Scene(root);
cena.getStylesheets().addAll(estilos);
return cena;
}
protected void configurarElementos() {
}
protected void definirTitulo(String titulo) {
if (stage != null) {
this.titulo = titulo;
stage.setTitle(titulo);
}
}
@Override
public void abrir() {
stage.show();
}
@Override
public void fechar() {
stage.close();
}
@Override
public void setModelo(URL modelo) {
this.modelo = modelo;
}
@Override
public void setEstilos(List<String> estilos) {
this.estilos = estilos;
}
}
这是Spring的aop配置和ControladorDialogoPrincipal bean的实例化:
<bean id="controladorDialogoPrincipal" class="com.hrgi.pdv.controladores.gui.dialogos.ControladorDialogoPrincipal"
init-method="init">
<property name="modelo" value="classpath:gui/dialogoPrincipal.fxml"/>
<property name="estilos" ref="estilos"/>
</bean>
<util:list id="estilos" list-class="java.util.ArrayList">
<value>/css/preVenda.css</value>
</util:list>
<aop:config>
<aop:aspect ref="dataSource">
<aop:pointcut id="todosOsMetodosIControladorDialogoPrincipal" expression="execution(* com.hrgi.pdv.controladores.gui.dialogos.IControladorDialogoPrincipal.*(..))"/>
<aop:before method="travarConexao" pointcut-ref="todosOsMetodosIControladorDialogoPrincipal"/>
</aop:aspect>
</aop:config>
我想调用此类的方法“travarConexao”:
public class RoutingDataSource extends AbstractRoutingDataSource implements Runnable {
.
.
.
private void definirConexaoAtual() {
if (conexaoTravada && conexaoAtual.equalsIgnoreCase("secundario"))
return;
DataSource principal = (DataSource) fontesDeDados.get("principal");
if (verificarConexao(principal)) {
synchronized (conexaoAtual) {
conexaoAtual = "principal";
}
} else {
synchronized (conexaoAtual) {
conexaoAtual = "secundario";
}
}
}
private boolean verificarConexao(DataSource principal) {
try {
Connection conexao = principal.getConnection();
Statement statement = conexao.createStatement();
return statement.executeQuery("SELECT 1") != null;
} catch (Exception e) {
return false;
}
}
public void travarConexao() {
System.out.println("\n\ncalled!!\n\n");
definirTravaDeConexao(true);
}
private void definirTravaDeConexao(Boolean trava) {
synchronized (conexaoTravada) {
conexaoTravada = trava;
}
definirConexaoAtual();
}
.
.
.
}
有人可以解释一下为什么从未调用此方法吗?
答案 0 :(得分:1)
在某些情况下,您无法使Spring AOP与JavaFX 2协同工作,因为JavaFX 2组件使用许多内部最终类,并且您无法有效地在CGLIB或Javassist中注入代理。实际上我没有尝试过AspectJ,但我相信这是同样的问题。
总而言之,如果你试图拦截一个自定义JavaFX组件内的方法(例如扩展GridPane),你将无法做到(或者你很幸运,但它不会适用于所有方法。)
如果您试图通过JavaFX控制器(不扩展javafx类)拦截方法,请确保Spring通过其上下文知道控制器(检查Spring JavaFX集成)。最后,如果没问题,请尝试使用CGLIB:
<aop:config proxy-target-class="false"/>
<aop:aspectj-autoproxy proxy-target-class="false"/>
答案 1 :(得分:1)
问题是配置不佳。在注意到我尝试过的切入点都没有工作(既不是最简单的)之后,我用Spring将纯Spring AOP改为AspectJ:
<aop:aspectj-autoproxy/>
<context:spring-configured/>
<bean class="com.hrgi.pdv.InterceptadorTravamentoConexao" scope="prototype">
<property name="routingDataSource" ref="dataSource"/>
</bean>
切入点被移动到特定新类中的注释:
@Aspect
@Configurable
public class InterceptadorTravamentoConexao {
private RoutingDataSource routingDataSource;
@Before("execution(* com.hrgi.pdv.controladores.gui.dialogos.IControladorDialogoPrincipal.*(..))")
public void travarConexao(){
routingDataSource.travarConexao();
}
public void setRoutingDataSource(RoutingDataSource routingDataSource) {
this.routingDataSource = routingDataSource;
}
}
在maven中为aspectj-compiler添加了一些配置:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<source>1.7</source>
<target>1.7</target>
<Xlint>ignore</Xlint>
<complianceLevel>1.7</complianceLevel>
<encoding>UTF-8</encoding>
<verbose>true</verbose>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.7.3</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.7.3</version>
</dependency>
</dependencies>
</plugin>
现在它正在运作。