0

我有一个使用 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();
    }
    .
    .
    .
}

有人可以解释一下为什么永远不会调用此方法吗?

4

2 回答 2

1

问题是配置不佳。在注意到我尝试过的切入点都不起作用(也不是最简单的)之后,我从纯 Spring AOP 更改为使用 Spring 的 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>

现在它正在工作。

于 2013-11-14T21:49:26.937 回答
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"/>
于 2013-11-14T14:25:50.367 回答