Framework de injeção de dependência revolucionário! Confiram!

28 respostas
B

Você deve estar se perguntando pow!!! Uma versão novo do spring, nem tava sabendo, mas num é nada disso, esta aqui hoje de bobeira em casa, aproveitando feriado prolongado e pensei! Vou construir um framework, primeiro pensei, construir um concorrente do hibernate, quem sabe domino o mundo com isso! Mas só de pensar no trabalho já me cansei, não ia conseguir concluir hoje!!! Ai pensei, injeção de dependência é legal, ta na moda, os programadores não querem mais manter o forte acoplamento!! Então vamos lá, vejam como usar.

import br.com.frameork.annotations.Dependencia;

/**
 * 
 * Computador um objeto que contem varios acoplamentos!
 * porem os computadores no mundo real seus acoplamentos
 * são plugaveis
 * 
 * para injetar a dependencia em um acoplamento é somente usar
 * a annotação @Dependencia
 *
 */
public class Computador {
	
	@Dependencia
	private Mouse mouse;

	@Dependencia
	private Teclado teclado;
	
	public void setMouse(Mouse mouse) {
		this.mouse = mouse;
	}

	public Mouse getMouse() {
		return mouse;
	}
	
	public void ligar() {
		System.out.println("opa! Iniciando o computador!!!");
		getMouse().testar();
		getTeclado().testar();
	}

	public void setTeclado(Teclado teclado) {
		this.teclado = teclado;
	}

	public Teclado getTeclado() {
		return teclado;
	}
	
}

Classes dos acoplamentos

public class Mouse {

	protected void testar() {
		System.out.println("mouse funfando!!!");
	}

}


public class Teclado {
	
	protected void testar() {
		System.out.println("teclado funfando!!!");
	}
	
}

Agora vamos ligar o computador!!! rsrsrs

public static void main(String[] args) {
		Computador computador = (Computador)Injetar.dependencias(Computador.class);
		computador.ligar();
 }

Saida no console: Bazinga!!! Sem NullPointException e sem acoplamento direto

opa! Iniciando o computador!!!
mouse funfando!!!
teclado funfando!!!

28 Respostas

R

Onde está a revolução? hehehe

R

To zuando cara… é bacana sim… mostra que vc tá entendendo da bagaça… eheheh

R

Na próxima versão… faça assim… (desafio)

Em alguma classe, coloque um método com um @StartApplication

Só pode haver 1 único método na aplicação com essa anotation…

Aí no seu main… vc faz apenas:

Injection.start();

O framework realiza a injeção de dependencia… e chama o método com o @StartApplication

B

pow mano que massa!! vou fazer sim e posto pra galera ver!! é trankilo fazer isso!! Mas me tira uma duvida outros frameworks fazem isso que você sugerio???

R

Fazem… ehehhe

Na minha assinatura… tem um por exemplo…

B

kkkk Que massa nem tinha visto!! Dei uma olhada no site do teu framework!! parabems exelente iniciativa! Essa ideia do framework é só zueira, não tenho tempo de me dedicar nesses projetos,porem quando puder vou ajudar em algum projeto opem!!.., Hoje que estava de bobeira e comecei a estudar um pouco sobre spring a ler algumas coisa a baixei uma apostila, acho que ela estava meio desatualizada, porque usava xml ao inves de annotations!! Ae resolvi brincar e fazer a injeção de uma forma menos complicada… hehehe é isso ae, parabems pelo projeto

P

:lol:

R

Heheh… mas começa é assim mesmo… tá no caminho!

B

Salve galera! Como hoje estava de bobeira fiz uma nova implementação no Framework “Ainda não tem nome alguem sugere algum???”! Sugestão de rogelgarcia:


Na próxima versão… faça assim… (desafio)

Em alguma classe, coloque um método com um @StartApplication

Só pode haver 1 único método na aplicação com essa anotation…

Aí no seu main… vc faz apenas:

Injection.start();

Pessoal olhem como ficou a versão 0.0.0.0.0.0.0.0.0.0,1.

package br.tete.classe;

public class Mouse {
	
	public void testar() {
		System.out.println("Algum tipo de mouse");
	}
	
}
package br.tete.classe;

import br.com.etex.annotations.Dependencia;

/**
 * 
 * Computador um objeto que contem varios acoplamentos!
 * porem os computadores no mundo real seus acoplamentos
 * são plugaveis
 * 
 * para injetar a dependencia em um acoplamento é somente usar
 * a annotação @Dependencia
 *
 */
public class Computador {
	
	
	private Mouse mouse;

	@Dependencia
	public void setMouse(Mouse mouse) {
		this.mouse = mouse;
	}
	
	public Mouse getMouse() {
		return mouse;
	}
	
	public void testar() {
		System.out.println("ligar computador");
		getMouse().testar();
	}
}

Vamos ao Main

package br.main;

import br.com.etex.Injetar;
import br.tete.classe.Computador;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		Injetar injetar = new Injetar(Computador.class);
		Computador computador = (Computador)injetar.getDependencias();
		computador.testar();
		
	}

}

Como esse é um super framework, podemos trabalhar com tipos polimórficos… olhem só

package br.tete.classe;

public class MouseOptico extends Mouse {
	
	@Override
	public void testar() {
		System.out.println("opa! Esse mouse é de luzinha");
	}
	
}
package br.tete.classe;

import br.com.etex.annotations.Dependencia;

public class Computador {
	
	
	private Mouse mouse;

	/**
	 * olhem só que maravilha!! em nosso computador
	 * podemos plugar um mouse optico tambem
	 * @param mouse
	 */
	@Dependencia(classe=MouseOptico.class)
	public void setMouse(Mouse mouse) {
		this.mouse = mouse;
	}
	
	public Mouse getMouse() {
		return mouse;
	}
	
	public void testar() {
		System.out.println("ligar computador");
		getMouse().testar();
	}
	
}

Agora vamos a sugestão do nosso amigo!

package br.tete.classe;

import br.com.etex.annotations.Dependencia;
import br.com.etex.annotations.Start;

public class Computador {
	
	
	private Mouse mouse;

	@Dependencia(classe=MouseOptico.class)
	public void setMouse(Mouse mouse) {
		this.mouse = mouse;
	}
	
	public Mouse getMouse() {
		return mouse;
	}
	
	/*
	 * Com a anotação start no méthodo podemos inverter
	 * o controle da execução deixando para o framework
	 */
	@Start
	public void testar() {
		System.out.println("ligar computador");
		getMouse().testar();
	}
	
}

vamos ao Main

package br.main;

import br.com.etex.Injetar;
import br.tete.classe.Computador;

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		Injetar injetar = new Injetar(Computador.class);
		injetar.start();
		
	}

}

É isso ai galera! Mais uma novidade no Framework! Alguém tem mais alguma sugestão para torna-lo ele cada vez melhor???

R

Essa anotação:

No método setMouse não é muito interessante pois você está acoplando a classe Computador a classe MouseOptico. É quase a mesma coisa de fazer setMouseOptico(…).

Que modificações você pode fazer para que isso não ocorra?

B

Não acho isso um problema e sim uma solução!! Pois em um mundo real o objetos são plugaveis! E com isso eu posso plugar qualquer tipo de mouse que for covariante de Mouse!!! MouseOptico, MouseBolinha…

uma ideia que tive agora, em tempo de execução trocar os acoplamentos!

Injetar.plugar(MouseBolinha.class);

R

Exatamente porque você poderá plugar outros tipos de mouse que isso pode ser um problema.

Você fixou na sua classe computador que é para injetar um mouse optico.

B

Sim! Poso plugar qualquer tipo que seja covariante de mouse! ou seja posso plugar um mouse Optico ou bolinha! Realmente não vejo problema nisso

R

@Dependencia(classe=MouseOptico.class) public void setMouse(Mouse mouse) { this.mouse = mouse; }

Só Injeta MouseOptico… por causa da anotação. O mouse foi forçado a ser um MouseOptico.

G

Muito legal!
Um ótimo jeito de entender profundamente um framework é criando um concorrente :slight_smile:

rogelgarcia:
@Dependencia(classe=MouseOptico.class) public void setMouse(Mouse mouse) { this.mouse = mouse; }Só Injeta MouseOptico… por causa da anotação. O mouse foi forçado a ser um MouseOptico.

Esse é o único probleminha que eu tinha observado, o suporte a injeção sem que a classe usuária precise determinar qual implementação usar.
É quase o mesmo que fazer private Mouse mouse = new MouseOptico().

B

hum!!! Saquei o que vc kiz dizer agora

B

Vou resolver esse problema tirando da minha anotação a propiedade classe… ae só vai poder injetar tipos definidos e não polimorficos…

alguma outra ideia para o framework??

V

Sugestões:
[list]jShot;[/list][list]Shot;[/list][list]iShot.[/list]
Fica aí a dica.
:smiley:

G

bobboyms:
Vou resolver esse problema tirando da minha anotação a propiedade classe… ae só vai poder injetar tipos definidos e não polimorficos…
alguma outra ideia para o framework??

Aí perde um pouco da graça, e parte importante da funcionalidade de um container de injeção de dependencia.
Tente criar um esquema de configuração revolucionário (para combinar com o framework revolucionário rs) que guarde essas informações em algum lugar externo às classes do sistema - para que o framework fique o menos intrusivo possível - mas sem a chatice dos XMLs do spring.

B

ta batizado o framework agora é jShot gostei do nome!!

B

Aí perde um pouco da graça, e parte importante da funcionalidade de um container de injeção de dependencia.
Tente criar um esquema de configuração revolucionário (para combinar com o framework revolucionário rs) que guarde essas informações em algum lugar externo às classes do sistema - para que o framework fique o menos intrusivo possível - mas sem a chatice dos XMLs do spring.

Criar o schema de configuração relolucionario ta phoda… eu ainda prefiro as anotações, mas como tu disse nem tudo vai poder ser via annotations…

Alguem tem ideia de um layout de arquivo revolucionário ???

B

Gelera essa é a estrutura do meu framework para IoC - injeção de dependencia, é algo muito simples, estou postando para o pessoal aprender um pouco mais sobre reflexão em java

package br.com.etex.annotations.injection;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Dependencia {
	
	Class<?> classe() default Class.class;
	boolean injetar() default true;
	
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Start {
	
	public boolean start() default true;
	
}
public interface Injetar {
	
	public void start();
	public Object getNovaInstancia();
	
}
package br.com.etex;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import br.com.etex.annotations.injection.Dependencia;
import br.com.etex.annotations.injection.Start;
import br.com.etex.exceptions.VariosStartException;
import br.com.etex.interfaces.Injetar;

public class InjecaoDependencia implements Injetar {
	
	private Object instancia;

	public InjecaoDependencia(Class<?> classe) {
		injetarDependencias(classe);
	}

	/**
	 * Verifica se é um methodo set
	 * 
	 * @param classe
	 */
	private boolean isSetMethodo(String nome) {
		if (nome.substring(0, 3).equals("set")) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 
	 * @param atributo
	 *            atributo que será injetado a dependencia
	 * @return String nome do methodo set do atributo exp : setAtributo
	 */
	private String nomeMethodo(Field atributo) {

		return "set" + atributo.getName().substring(0, 1).toUpperCase()
				+ atributo.getName().substring(1, atributo.getName().length());
	}

	private Object getInstancia(Object objeto, Method method)
			throws InstantiationException, IllegalAccessException {

		Object instancia = null;

		for (Field field : objeto.getClass().getDeclaredFields()) {

			if (nomeMethodo(field).equals(method.getName())) {
				instancia = field.getType().newInstance();
				break;
			}
		}

		return instancia;
	}

	@Override
	public Object getNovaInstancia() {
		return getInstancia();
	}
	
	/**
	 * 
	 * @param classe
	 *             Classe qual deve ser criada uma nova instancia
	 *             com suas dependencias ja injetadas
	 * @return Object
	 *             retorna uma instancia com classe ja injetada
	 */
	private Object injetarDependencias(Class<?> classe) {

		Object objeto = null;
		Dependencia dependencia = null;

		try {

			objeto = classe.newInstance();

			for (Method method : objeto.getClass().getDeclaredMethods()) {

				for (Annotation annotation : method.getDeclaredAnnotations()) {

					if (annotation instanceof Dependencia) {
						dependencia = (Dependencia) annotation;

						if (dependencia.injetar()) {
							Class<?> tipoClasse = null;
							Object objetoAtributo = null;

							if (dependencia.classe() == Class.class) {

								if (isSetMethodo(method.getName())) {

									if (getInstancia(objeto, method) != null) {
										method.invoke(objeto,
												new Object[] { getInstancia(
														objeto, method) });
									}
								}
							} else {

								tipoClasse = dependencia.classe();
								objetoAtributo = tipoClasse.newInstance();

								if (isSetMethodo(method.getName())) {
									method.invoke(objeto,
											new Object[] { objetoAtributo });
								}
							}
						}
					}
				}
			}

		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}

		setInstancia(objeto);
		return objeto;
	}
	
	/**
	 * verifica se existe varias annotações @start
	 * se tiver mais que uma gera a exception 
	 * {@link VariosStartException}
	 */
	private void validaStartAnnotation() {
		
		int qtd = 0;
		
		for (Method method : getInstancia().getClass().getDeclaredMethods()) {

			for (Annotation annotation : method.getDeclaredAnnotations()) {
				if (annotation instanceof Start) {
					qtd++;
				}
			}
		}
		
		if(qtd > 1) {
			try {
				throw new VariosStartException();
			} catch (VariosStartException e) {
				e.printStackTrace();
			}
		}
	}

	
	/**
	 * inicia um methodo que esta anatado
	 * com start para ser iniciado altomaticamento
	 */
	public void start() {
		
		Start start = null;
		validaStartAnnotation();
		for (Method method : getInstancia().getClass().getDeclaredMethods()) {

			for (Annotation annotation : method.getDeclaredAnnotations()) {

				if (annotation instanceof Start) {
					start = (Start) annotation;

					if (start.start()) {
						try {
							method.invoke(getInstancia(), new Object[] {});
						} catch (IllegalArgumentException e) {
							e.printStackTrace();
						} catch (IllegalAccessException e) {
							e.printStackTrace();
						} catch (InvocationTargetException e) {
							e.printStackTrace();
						}
					}
				}
			}
		}
	}
	
	
	private void setInstancia(Object instancia) {
		this.instancia = instancia;
	}

	private Object getInstancia() {
		return instancia;
	}


}

É isso ae galera esse é o revolucionário framework de injeção de controle, ta ae os fontes para copiar, colar, melhorar… etc… bla bla blaa…
Se alguem tiver alguma duvida sobre alguma coisa pode perguntar

D

Achei muito interessante o código mas quando tento usar o eclipse apresenta o seguinte erro: “The annotation @Dependencia is disallowed for this location”.

B

Corrige os pacotes

provavelmente você não esta usando mesma estrutura de pacotes que eu usei.

S

Depois de 7 anos as pessoas comecam a abandonar XML e Annotations. A moda agora é configuracão programática, DSL, etc.

Parabéns pelo framework. Continue desenvolvendo ele. No mínimo vc vai aprender bastante.

Dá uma olhada também no MentaContainer, que é um framework de IoC, DI e AutoWiring completo que compete com Guice, Pico e Spring. E totalmente baseado em configuracão programática.

http://mentacontainer.soliveirajr.com/posts/list/5.page

B

saoj:

Tente criar um esquema de configuração revolucionário (para combinar com o framework revolucionário rs) que guarde essas informações em algum lugar externo às classes do sistema - para que o framework fique o menos intrusivo possível - mas sem a chatice dos XMLs do spring.

Depois de 7 anos as pessoas comecam a abandonar XML e Annotations. A moda agora é configuracão programática, DSL, etc.

Parabéns pelo framework. Continue desenvolvendo ele. No mínimo vc vai aprender bastante.

Dá uma olhada também no MentaContainer, que é um framework de IoC, DI e AutoWiring completo que compete com Guice, Pico e Spring. E totalmente baseado em configuracão programática.

http://mentacontainer.soliveirajr.com/posts/list/5.page

saoj. Esse framework foi apenas uma brincadeira que eu fiz, para que de forma simplificada as pessoas possam entender um pouco como funciona internamente os frameworks de IoC…

D

Não sei se é isso o problema, veja como deixei a estrutura:

br.com.etex
----InjecaoDependencia

br.com.etex.annotations.injection
----Dependencia
----Injetar
----Start

A

Galera essa bagaça ta começando a ficar séria mas está show de bola. haha

Criado 24 de junho de 2011
Ultima resposta 12 de jan. de 2012
Respostas 28
Participantes 8