2013-11-14 59 views
0

我有USSE的JavaFX 2应用程序,我想确保一个特定的代码被称为一个接口的每一个方法:无法拦截切入点Spring AOP实现

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; 
    } 
} 
实现上述接口的类10

下面是AOP的Spring的配置和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

你可以在你的应用程序上下文或者spring配置文件中发布更多的信息以获得完整的感觉吗? –

+0

Hi @DiegoJimeno,我在问题中添加了更多信息 – brevleq

回答

0

问题是配置不佳。注意到,没有切入点的我tryied工作(无论是简单的),我从纯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; 
    } 
} 

加入过多的AspectJ的编译器的一些配置在行家:

<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> 

现在正在工作。

1

有些情况下,您无法使Spring AOP与JavaFX 2一起工作,因为JavaFX 2组件使用许多内部最终类,并且无法高效地向CGLIB或Javassist注入代理。其实我还没有尝试过使用AspectJ,但我相信这是同样的问题。总而言之,如果您试图拦截一个定制JavaFX组件内部的方法(例如扩展GridPane),那么您将无法做到这一点(或许您运气不错,但它赢得了' t适用于所有方法)。

如果你试图拦截通过一个JavaFX控制器的方法(不延伸JavaFX类),确保Spring知道通过其上下文控制器(检查你的春天JavaFX的整合)。最后,如果没问题,请尝试使用CGLIB:

<aop:config proxy-target-class="false"/> 
<aop:aspectj-autoproxy proxy-target-class="false"/> 
+0

嗨@zenbeni,有没有办法绕过这个限制?在所有需要它的方法中调用travarConexao是非常糟糕的。 – brevleq

+0

@brevleq我不确切地知道你需要什么,你是否检查过你的AOP配置是否正确,并且在香草Spring beans上有基本的切入点?尝试在Spring中定义一个基本的HelloWorldService,并在一个方法上添加一个切入点,然后看看会发生什么。如果它不起作用,那么javafx不是问题,可能是依赖/配置问题(有或没有cglib)。 – zenbeni