Annotations com Spring 2.5 + Thinlet
O Spring Framework a partir de sua versão 2.5 introduziu uma quantidade considerável de annotations a disposição do desenvolvedor. Ainda é possível usar a configuração clássica em XML, mas agora além dos recursos de anotações é possível mesclar os dois no mesmo código.
Vou demonstrar através de um exemplo simples utilizando como GUI o Thinlet. O Thinlet é uma biblioteca que permite a criação de GUI através de definição em XML da interface, como se fosse um XUL, o que dá muita flexibilidade. O projeto de GUI está meio parado, acho que o ultimo release foi em 2005, mas mesmo assim, é uma biblioteca simples de se usar e principalmente muito leve.
Foi utilizado o Spring Framework 2.5 mas pode ser usado qualquer versão do mesmo sendo 2.5.x. Vamos ver como utilizar algumas anotações que o Spring introduziu aos seus usuários. Também vou abordar como integrar o uso dessas anotações com o desenvolvimento em XML clássico.
Dependências:
A Definição da GUI via o Thinlet segue a baixo. Você deve chamar esse arquivo de
Calculator.XML.
Eu criei o Enumeration Operation para a representação das operações da calculadora. Segue o código a baixo.
Para realizar as operações matemáticas eu criei um Service e chamei de CalculatorService. Segue a baixo.
Esse Service possui o método calculate que recebe dois Double como parâmetros mais uma objeto do tipo Operation que é a operação que deve ser efetuada, a partir da instância do objeto de Operation o serviço decide qual operação deve ser efetuada.
@Component: Aqui que começa a brincadeira. Com essa anotações estamos dizendo para o Spring que essa classe é um componente, logo se a mesma for scaneada ela irá para a BeanFactory do Spring. Isso é o mesmo que fazer a declaração do Bean no xml informando id e class. Por default o id do bean será o nome da classe, mas essa informação pode ser modificada.
Agora vamos a tela. Classe Calculator
@Component(value="calc"): Com isso estamos declarando que a classe Calculator é um componente no Spring, ou seja, um bean no contexto do Spring. Com o parametro value estou disendo que o identificador desse componente é "calc" que é na verdade o id do bean.
@Autowired private CalculatorService cs;: Com essa anotação estou fazendo uma injeção de dependências, como eu usei !Autoeired o spring ira aplicar auto-wire by type, nesse exemplo não exite problema pois estou lidando direto com a classe concreta porem cuidado com esse recurso ele pode dar muitas dores de cabeça se for usado impropriamente.
Para rodar a aplicação crie a classe MainApp. Segue a baixo.
Nessa classe o contexto do Spring é subido. E um bean é recuperado do contexto. Você ira entender mais sobre o que está aconetcendo no proximo tópico que é o contexto do spring.
spring-beans.xml
Esse é o clássico xml de beans do Spring. Vocês podem notar de novo os nodos:
<context:annotation-config/>
<context:spring-configured/>
<context:component-scan base-package="com.blogspot.diegopacheco" annotation-config="true" />
Esses são os nodos necessários para o uso de anotações no Spring. Um recurso muito legal que o Spring introduziu é o context:compoment-scan com esse recurso o spring passa um scanner no seu class-path a procura de beans. Adivinhe que beans ele ira adicionar ao contexto? Ele irá adicionar o que contem a acontação @Component.
No final é definido o bean thinlet.FrameLauncher que é um utilitário do Thinlet para iniciar as aplicações. Ele foi definido como um bean normal do Spring, porem foi feito via constructor injection a injeção do bean "calc" que na verdade ira ser carregado pela scanner do Spring. Dessa forma conseguimos injetar beans oriundos de XML ou anotações, no spring 2.5 isso tudo é transparente.
Ainda existem muitos recursos no Spring 2.5 em relação a anotações. Vale a pena conferir. Mas por hoje é só. :)
Vou demonstrar através de um exemplo simples utilizando como GUI o Thinlet. O Thinlet é uma biblioteca que permite a criação de GUI através de definição em XML da interface, como se fosse um XUL, o que dá muita flexibilidade. O projeto de GUI está meio parado, acho que o ultimo release foi em 2005, mas mesmo assim, é uma biblioteca simples de se usar e principalmente muito leve.
Foi utilizado o Spring Framework 2.5 mas pode ser usado qualquer versão do mesmo sendo 2.5.x. Vamos ver como utilizar algumas anotações que o Spring introduziu aos seus usuários. Também vou abordar como integrar o uso dessas anotações com o desenvolvimento em XML clássico.
Dependências:
- spring framework 2.5.x
- commons-logging
- spring-aspects
- aspectjrt
- thinlet
A Definição da GUI via o Thinlet segue a baixo. Você deve chamar esse arquivo de
Calculator.XML.
Eu criei o Enumeration Operation para a representação das operações da calculadora. Segue o código a baixo.
package com.blogspot.diegopacheco.thinletspring25; /** * Enum que define as operações matematicas. * * @author Diego Pacheco * @version 1.0 */ public enum Operation { SOMA { return 0; } }, SUBTRACAO { public int getValue() { return 1; } }, DIVISAO { public int getValue() { return 2; } }, MULTIPLICACAO { public int getValue() { return 3; } }; public int getValue() { return -1; } }
Para realizar as operações matemáticas eu criei um Service e chamei de CalculatorService. Segue a baixo.
pre package com.blogspot.diegopacheco.thinletspring25; import org.springframework.stereotype.Component; /** * Classe de Serviço da Calculadora * * @author Diego Pacheco * @version 1.0 */ @Component public class CalculatorService { public Double calculate(Double v1, Double v2, Operation op) { Double result = 0d; switch (op.getValue()) { case 0: result = v1 + v2; break; case 1: result = v1 - v2; break; case 2: result = v1 / v2; break; case 3: result = v1 * v2; break; default: throw new RuntimeException("A operacao[" + op + "] não é suportada pelo service."); } return result; } }
Esse Service possui o método calculate que recebe dois Double como parâmetros mais uma objeto do tipo Operation que é a operação que deve ser efetuada, a partir da instância do objeto de Operation o serviço decide qual operação deve ser efetuada.
@Component: Aqui que começa a brincadeira. Com essa anotações estamos dizendo para o Spring que essa classe é um componente, logo se a mesma for scaneada ela irá para a BeanFactory do Spring. Isso é o mesmo que fazer a declaração do Bean no xml informando id e class. Por default o id do bean será o nome da classe, mas essa informação pode ser modificada.
Agora vamos a tela. Classe Calculator
package com.blogspot.diegopacheco.thinletspring25; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import thinlet.Thinlet; /** * Esse é um gui definido atres do Thinlet. * @author Diego Pacheco * @version 1.0 */ @Component(value="calc") public class Calculator extends Thinlet { private static final long serialVersionUID = 1L; @Autowired private CalculatorService cs; public Calculator() throws Exception { add(parse(Calculator.class.getSimpleName() + ".xml")); } public void calculate(String number1, String number2, String operation, Object result) { try { Double v1 = Double.parseDouble(number1); Double v2 = Double.parseDouble(number2); Operation op = null; if("+".equals(operation)){ op = Operation.SOMA; }else if("-".equals(operation)){ op = Operation.SUBTRACAO; }else if("/".equals(operation)){ op = Operation.DIVISAO; }else if("*".equals(operation)){ op = Operation.MULTIPLICACAO; } setString(result, "text", String.valueOf(cs.calculate(v1, v2,op))); } catch (NumberFormatException nfe) { getToolkit().beep(); } } public CalculatorService getCs() { return cs; } public void setCs(CalculatorService cs) { this.cs = cs; } }
@Component(value="calc"): Com isso estamos declarando que a classe Calculator é um componente no Spring, ou seja, um bean no contexto do Spring. Com o parametro value estou disendo que o identificador desse componente é "calc" que é na verdade o id do bean.
@Autowired private CalculatorService cs;: Com essa anotação estou fazendo uma injeção de dependências, como eu usei !Autoeired o spring ira aplicar auto-wire by type, nesse exemplo não exite problema pois estou lidando direto com a classe concreta porem cuidado com esse recurso ele pode dar muitas dores de cabeça se for usado impropriamente.
Para rodar a aplicação crie a classe MainApp. Segue a baixo.
package com.blogspot.diegopacheco.thinletspring25; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Classe de entrada para aplicação. * @author Diego Pacheco * @version 1.0 */ public class MainApp { public static void main(String[] args) throws Exception{ ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring-beans.xml"); ac.getBean("frameLauncherPrincipal"); } }
Nessa classe o contexto do Spring é subido. E um bean é recuperado do contexto. Você ira entender mais sobre o que está aconetcendo no proximo tópico que é o contexto do spring.
spring-beans.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd" default-autowire="no" default-dependency-check="none" default-lazy-init="true" > <context:annotation-config/> <context:spring-configured/> <context:component-scan base-package="com.blogspot.diegopacheco" annotation-config="true" /> <bean id="frameLauncherPrincipal" class="thinlet.FrameLauncher" lazy-init="true" > <constructor-arg index="0" value="Calculatora Simples" /> <constructor-arg index="1"> <ref bean="calc" /> </constructor-arg> <constructor-arg index="2" value="300" /> <constructor-arg index="3" value="80" /> </bean> </beans>
Esse é o clássico xml de beans do Spring. Vocês podem notar de novo os nodos:
<context:annotation-config/>
<context:spring-configured/>
<context:component-scan base-package="com.blogspot.diegopacheco" annotation-config="true" />
Esses são os nodos necessários para o uso de anotações no Spring. Um recurso muito legal que o Spring introduziu é o context:compoment-scan com esse recurso o spring passa um scanner no seu class-path a procura de beans. Adivinhe que beans ele ira adicionar ao contexto? Ele irá adicionar o que contem a acontação @Component.
No final é definido o bean thinlet.FrameLauncher que é um utilitário do Thinlet para iniciar as aplicações. Ele foi definido como um bean normal do Spring, porem foi feito via constructor injection a injeção do bean "calc" que na verdade ira ser carregado pela scanner do Spring. Dessa forma conseguimos injetar beans oriundos de XML ou anotações, no spring 2.5 isso tudo é transparente.
Ainda existem muitos recursos no Spring 2.5 em relação a anotações. Vale a pena conferir. Mas por hoje é só. :)