Injeção de dependência
A injeção de dependência é um design pattern que visa desacoplar os componentes da aplicação. Os componentes são instanciados externamente a classe. Um gerenciador controla essas instancias. Os componentes tem dependencias entre si. Esse gerenciador, através de uma configuração, liga os componentes de forma a montar a aplicação. Por exemplo:
public class ExecutaQuery {

	private Conexao conexao;
	
	public void setConexao(Conexao conexao){
		this.conexao = conexao;
	}
	
	public Conexao getConexao(){
		return conexao;
	}
	
	(...)
}
public class Conexao {

	(...)
	
}
Suponhamos uma classe ExecutaQuery que execute queries em um banco de dados. Para executar uma query uma conexão com o banco de dados é necessária. Essa conexão é representada pela classe Conexao. A classe ExecutaQuery possui um setter para conexao, ela precisa de uma conexão com o banco de dados para executar as queries. Em um ambiente normal o código para criar e configurar seria como o exemplo:
ExecutaQuery executaQuery = new ExecutaQuery();
Conexao conexao = new Conexao();
	
executaQuery.setConexao(conexao);
Para uma pequena aplicação esse código é simples. Mas em aplicações grandes com várias classes e várias dependências isso se torna bem complexo. O framework faz exatamente o que o código acima faz, mas o programador não precisa instanciar e nem configurar esses beans.

Um framework de injeção de dependencias irá criar e configurar os beans sem a necessidade de programação. O NEO utiliza para a injeção de dependências o framework Spring (www.springframework.org). O Spring possui uma fábrica que gerencia a criação e configuração dos beans. O NEO registra as classes nessa fábrica para a criação e configuração desses objetos. O NEO possui uma forma de registro de classes que dispensa o uso de XML, mas ainda é possível registrar os beans através do XML do Spring.
Configurando beans com annotations (@Bean)
Para utilizar a injeção de dependências é necessário uma fábrica que crie e configure os objetos da aplicação. Para a criação dessa fábrica é necessário a utilização de um listener (br.com.linkcom.neo.core.web.init.ContextLoaderListener) que deve ser configurado no web.xml. Esse listener cria e configura a fábrica do Spring. Essa classe extende o ContextLoaderListener do Spring. Portanto, qualquer configuração aplicável ao listener do Spring é também aplicavel ao NEO.
Exemplo de web.xml com o listener:
[JSP]
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
	xmlns="http://java.sun.com/xml/ns/j2ee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
	[ATTR]http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	
	<listener>
		<listener-class>br.com.linkcom.neo.core.web.init.ContextLoaderListener</listener-class>
	</listener>
	
</web-app>	
Com o listener configurado podemos colocar beans na fábrica do Spring. O NEO permite a utilização de anotations para a configuração desses beans. Para configurar um bean para a fábrica basta anotar a classe com @Bean. Vamos voltar ao exemplo do ExecutaQuery e Conexao para ver como a configuração desses beans seria feita no NEO.
import br.com.linkcom.neo.bean.annotation.Bean;

@Bean
public class ExecutaQuery {

	private Conexao conexao;
	
	public void setConexao(Conexao conexao){
		this.conexao = conexao;
	}
	
	public Conexao getConexao(){
		return conexao;
	}
	
	(...)
}
import br.com.linkcom.neo.bean.annotation.Bean;

@Bean
public class Conexao {

	(...)
	
}
O NEO detecta a presença da anotação @Bean e registra as classe na fábrica do Spring. Como a classe ExecutaQuery possui um setter para Conexao, ele será chamado passando como parâmetro a instancia de Conexao que foi criada. Apenas uma instancia de cada classe é criada, mesmo que mais de um objeto tenha dependencia de uma mesma classe. Os objetos no NEO são criados utilizando o design pattern singleton.
Note que, se a classe Conexao não estivesse anotada com @Bean nenhum bean da classe Conexao seria criado e o método setConexao(...) de ExecutaQuery não seria chamado.
Importante: Apenas as classes que estiverem dentro de /WEB-INF/classes serão registradas. O NEO não lê as classes que estiverem dentro de pacotes JAR dentro do lib da aplicação.
Para buscar os beans registrados na aplicação existem duas formas. Utilizando a factory do Spring:
WebApplicationContext webApplicationContext = NeoWeb.getWebApplicationContext(servletContext);
DefaultListableBeanFactory factory = webApplicationContext.getConfig().getDefaultListableBeanFactory();
ExecutaQuery executaQuery = (ExecutaQuery) factory.getBean("executaQuery");
Buscando pelo NEO:
NeoWeb.getWebApplicationContext(servletContext);
ExecutaQuery executaQuery = Neo.getObject(ExecutaQuery.class);
O método getWebApplicationContext(...) é utilizado apenas para inicializar o contexto do NEO. O NEO possui dois contextos: de aplicação e de requisição. O contexto de aplicação é equivalente ao contexto de aplicação do J2EE e o contexto de requisição é equivalente ao contexto de requisição do J2EE. A fábrica do Spring é guardada no escopo de aplicação por isso é necessário inicializar o contexto de aplicação antes de buscar algum bean da fábrica.

Existe uma outra forma de utilizar o contexto NEO sem a necessidade de criá-lo explicitamente. Para utilizar essa forma é necessário cadastrar um filtro no web.xml:
[JSP]
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
	xmlns="http://java.sun.com/xml/ns/j2ee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
	[ATTR]http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	
	<listener>
		<listener-class>br.com.linkcom.neo.core.web.init.ContextLoaderListener</listener-class>
	</listener>
	
	<filter>
		<filter-name>neoFilter</filter-name>
		<filter-class>br.com.linkcom.neo.core.web.NeoFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>neoFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	
</web-app>
Com esse filtro, para utilizar um bean gerenciado basta utilizar o seguinte código:
ExecutaQuery executaQuery = Neo.getObject(ExecutaQuery.class);
Passando apenas a classe desejada o NEO retorna um objeto configurado.
Nesse caso, a chamada:
executaQuery.getConexao();
Retornaria uma instancia de Conexao. Já que ela foi configurada através da injeção de dependencias em ExecutaQuery.
Configurando relacionamentos
Apenas o fato de colocar um setter para uma propriedade faz com que o NEO configure automaticamente a classe. Mas é possível escolher qual bean utilizar para configurar determinada propriedade. A escolha de qual bean configurar em determinada propriedade pode ser útil em alguns casos.
Vamos entender como funciona a fábrica do Spring.
A fábrica do Spring contém uma coleção de todas as classes e configurações para instanciar os beans. Cada configuração dentro dessa fábrica representa um bean. Uma configuração deve definir no mínimo um nome e uma classe. É possível ter, dentro de uma fábrica, vários beans de uma mesma classe. Mas cada configuração deve ter um nome diferente. Por isso, o que identifica um bean dentro da fábrica é o seu nome.
Quando utilizamos a anotação @Bean o nome que a classe é registrada no Spring é o nome simples da classe (sem o pacote) com a primeira letra minúscula. Se temos uma classe a.b.c.MinhaClasse anotada com @Bean o nome que essa classe será registrada será 'minhaClasse'.
A anotação @Bean permite que o nome de registro do bean seja alterado através da propriedade name. Veja o exemplo:
import br.com.linkcom.neo.bean.annotation.Bean;

@Bean(name="c")
public class Conexao {
}	
Agora para conseguir um bean de Conexao o nome informado deve ser 'c'. Exemplo:
DefaultListableBeanFactory factory = Neo.getApplicationContext().getConfig().getDefaultListableBeanFactory();
Conexao conexao = (Conexao) factory.getBean("c");
Não é possível utilizar o método resumido do NEO (Neo.getObject(...)) para buscar beans cujo nome não seja o nome da classe com a primeira letra minúscula.
Dica: Utilize a anotação @Bean sem a propriedade name, isso faz com que o código fique mais limpo e seja possível utilizar a forma resumida do NEO para buscar os beans.
Para alterar o mapeamento de alguma propriedade utilizamos a anotação @Ref no setter da propriedade. Exemplo:
import br.com.linkcom.neo.bean.annotation.Bean;

@Bean
public class ExecutaQuery {

	private Conexao conexao;
	
	@Ref("c")
	public void setConexao(Conexao conexao){
		this.conexao = conexao;
	}
	
	public Conexao getConexao(){
		return conexao;
	}
	
	(...)
}
Nesse caso estamos configurando a propriedade conexao com o bean 'c'. Se não existir o bean 'c' na fábrica do Spring uma exeção será lançada ao iniciar a aplicação.
Configurando beans através de XML
Apesar de não ser necessário, a configuração de beans pode também ser feita através do XML do Spring. No neo o xml padrão é o applicationConfig.xml. Esse xml deve ficar dentro da pasta /WEB-INF/ da aplicação.
Importante: No Spring o xml de configuração padrão é applicationContext.xml no Neo é applicationConfig.xml
Exemplo de XML de configuração:
[JSP]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
.
.
.
</beans>
Esse XML pode ser útil para fazer configurações de banco de dados e envio de e-mail por exemplo. A configuração desse XML é igual a configuração de um XML do Spring que não esteja utilizando o NEO. Para mais informações sobre a configuração via XML do Spring visite o site www.springframework.org
Organização da aplicação
Em uma aplicação profissional é importante separar as tarefas diferentes em classes diferentes. No neo é recomendada a utilização da seguinte organização: Qualquer classe que extender MultiActionController, GenericService ou GenericDAO não precisa ser anotada com @Bean. Uma explicação melhor sobre essas classes será feita nos capítulos seguintes.