Eu ainda não lí o artigo, quando ler darei um feedback mais preciso.
Atualmente eu utilizo Spring com aspectJ com compile time weaving. É uma mão na roda! Você ganha muito mais controle do que utilizando EJB3, podendo fazer injeção de dependências em qualquer lugar, controle de transação em qualquer lugar etc
Decidi por essa abordagem pois “herdei” um sistema que fazia tudo na mão… controle de transações, segurança etc. Havia muito código duplicado e ocorriam alguns bugs devido a esquecimento de fechar transação, fechar conexão, executar um rollback em caso de exception etc.
Como não haviam testes e o sistema não era bem projetado, optei por utilizar Spring com aspecto para poder interceptar qualquer ponto do código para demarcação de transações. Foi bem simples, em cerca de 2 dias consegui migrar o sistema de 70k linhas de código para o controle do Spring.
Um dia desses, pra brincar, usei o aspectj com o spring pra interceptor toda chamada
de método (com alguns filtros) e então extrair um report de tempos por método, média,
quantidade de chamadas, etc. Tudo aquilo que o profile do netbeans faz.
Utilizar aspectos é mais comum do que se imagina. O próprio EJB 3 vem com o que ele chama de Interceptor, mas que na verdade é uma adaptação do JBoss AOP. E o legal é que você pode aproveitar os recursos do CDI, por exemplo, e de uma maneira mais clara do que utilizando aspectJ. No livro “Real World Java EE Patterns” tem uns exemplos bacanas, como esse que segue:
public class AuditInterceptor{
@EJB
private Audit audit;
@AroundInvoke
public Object trace(InvocationContext ic) throws Exception{
String info = "Method: " + ic.getMethod() + "\n";
info += "Object: " + ic.getTarget().getClass().getName();
this.audit.audit(info);
return ic.proceed();
}
}
Na verdade os interceptors não são bem uma implementação de AOP, apesar de várias vezes poderem ser utilizados com o mesmo propósito. A grande diferença está na existência do “pointcut” que é uma expressão do aspecto que diz onde ele irá interceptar a aplicação. Com o uso de interceptors muitas vezes isso precisa ser configurado individualmente em cada classe. Quanto mais ricas as expressões para pointcut, mais poderosa é a implementação de aspectos.
Os Interceptors do EJB são sim uma implementação de AOP. Tudo bem que não suportam pointcuts como o JBoss AOP, no qual ele se baseia, mas você deve pensar do ponto de vista de crosscutting concerns. Você também pode incluir Default Interceptors, que interceptam qualquer classe na aplicação. Mas sim, com certeza o AspectJ ou outro framework AOP “completo” é mais poderoso…
Talvez você esteja se perguntando “mas qual a diferença, dá para implementar com os dois!”. Desculpe o preciosismo, mas como pesquisador da área as vezes a gente tem que ser meio chato com as definições…
Aí é questão de ponto de vista. Como falei, com EJB 3.0 é possível definir Default Interceptors, que atingirão todas as classes da aplicação. Além disso, definir quais classes serão afetadas por um aspecto, mesmo que explicitamente no caso de anotar uma classe, é uma forma de pointcut, na minha opinião. E ali onde você viu o @AroundInvoke no código anterior seria o advice. Eu não vejo porque não considerar isso um aspecto, inclusive não acho que essa implementação contrasta com a definição formal de aspecto, mas como já falei antes, é apenas minha opinião.
Na verdade ao anotar a classe, a classe tem conhecimento de que está a interceptando. Uma característica impotante da AOP é a “ignorância” (obliviousness) da classe em relação aos aspectos que a estão modificando. Seria em OO algo próximo ao desacoplamento.
Na verdade essa não é apenas minha opinião, mas de toda comunidade acadêmica da área!
Me desculpe estar sendo meio chato e insistente, mas é que muita gente tem essa mesma concepção sobre AOP. Quando se percebe que a AOP é muito maior do que um simples uso de interceptors, que existem muitas outras possibilidades, um novo universo se abre!
Essa rigidez formal não vai levar a projetos melhores. Não sei exatamente o motivo, mas certamente o JCP considerou o uso de pointcuts(ou o JBoss AOP completo) como ferramenta de AOP para o EJB. Devem ter tido bons motivos para rejeitar. Pointcuts são apenas um conceito, a forma de implementar é aberta. Esqueça a palavra chave pointcut do AspectJ e pense como um conceito. Ainda no EJB 3.0, por exemplo, você não precisa marcar um método como transacional para que ele seja transacional num servidor de aplicação. Transação é um dos requisitos ortogonais mais batidos de todos. Além disso, você não precisa “desanexar” um objeto e transformá-lo num DTO, como se fazia antes. Isso é obliviousness, isso é AOP. Default Interceptor é obliviousness, é AOP. E demarcação de classes pode não ser obliviousness mas endereça o objetivo da AOP que é modelar um requisito ortogonal.
Concordo que pointcuts são um conceito, mas discordo que a especificação EJB 3 a implemente. Discordo também que Default Interceptors seja parecido com obliviousness. Os pointcuts são feitos para selecionar os pontos interceptados e a única implementação possível dos default interceptors todos os EJBs.
Na verdade o que estou falando não é sobre rigidez formal, e sim sobre um conceito importante que não está sendo bem interpretado. O entendimento desse conceito e sua utilização pode levar sim a projetos melhores! Por exemplo, ao invés de ter que configurar um interceptor em várias classes (vamos supor que não são todas, mas um subconjunto delas), você poderia configurar isso uma vez só em uma definição de pointcut. Essa solução tornam as classes desacopladas dos aspectos! Essa solução permite que esse subconjunto seja modificado mais facilmente!
Discordo mais uma vez quando assume que a JCP sempre escolhe as melhores soluções. O JPA 1.0, por exemplo, não incluiu Criteria que já tinha no Hibernate. Foi adicionado na JPA 2.0. Já vi várias vezes coisas desse tipo! As especificação do EJB vive aprendendo novas lições com o Spring que ele já implementa a um bom tempo… Então acho errado assumir que se não foi incluído na especificação, então não é uma boa solução ou a melhor solução.
Esse é o ponto, cara. Você acha que pra criar um aspecto é necessário um pointcut que defina uma expressão regular. Isso não é regra. Um Default Interceptor seria um pointcut com um *, fazendo um paralelo do seu ponto de vista com o do AspectJ. Entenda que aspecto é apenas uma unidade funcional, assim como uma classe, que encapsula um requisito transversal. Isso é um aspecto. A forma como ele vai encapsular não importa. Claro que os interceptadores do EJB 3 não se propõem a ser algo tão poderoso como o AspectJ, claro que Aspectj suporta muito mais formas de “corte” que o EJB. Acontece que as funcionalidades que mencionei anteriormente são uma forma de modelar um requisito transversal. Bastante simples, talvez você diga bastante limitadas ou rudimentares, mas ainda assim úteis. Só pra terminar essa questão do “obliviouness”, em qualquer documentação de qualquer framework AOP você vai encontrar pointcuts que interceptam uma única classe ou um único método de uma única classe, só pra você entender que isso de ter um “intervalo de interceptação” nem sempre é verdadeiro e esse não é o problema.
O engraçado é que o post era sobre um artigo e o incentivo do uso de aspectos e eu tirei um exemplo justamente de um livro chamado Real World Java EE Patterns, o cara usando no “mundo real”. Ele usa claramente a palavra aspectos, mas nem queria entrar nesse mérito afinal ele não é “acadêmico”. E aí você se deixa levar por uma questão menor de expressões regulares quem fundamentam obliviousness. Eu suspeito que o problema é que o artigo seria sobre o uso de AspectJ.
Quanto a JCP, eu me lembrei de uma entrevista com um dos projetistas do Java em que ele comentou sobre a inclusão de suporte a aspectos diretamente na linguagem Java, e ele disse que isso não será feito para que a linguagem não se torne complexa demais.
Enfim, acho melhor terminarmos essa discussão por aqui, porque notadamente temos pontos de vista diferentes. Você acha imprescindível uma expressão pointcut e eu defendo que aspecto é apenas uma unidade funcional para modelar crosscut concerns.
Vamos terminar a discussão por aqui sim… Já colocamos nosso ponto de vista para que cada um possa ler e tirar suas próprias conclusões. Deixei os links dos artigos que citei para os que quiserem se aprofundar. De qualquer forma, agradeço por debater comigo esse tema que considero relevante e mantendo o foco no aspecto técnico da questão.
Termino por aqui deixando claro que não sou contra o uso de interceptors e apenas afirmo que eles são uma abordagem diferente de AOP para modularizar interesses transversais. Ao perceberem que são coisas diferentes, os desenvolvedores podem entender melhor o potencial do uso de AOP em um projeto e se aprofundar nesses conceitos.
Na orientação a aspectos, é responsabilidade do aspecto saber onde ele deve atuar. No uso de interceptors, essa definição não é responsabilidade do interceptor. Essa é a diferença chave entre as duas abordagens. Por mais que pareça boba, pode ter um grande impacto em desacoplamento e manutenibilidade. Essa é uma característica de toda abordagem que se chama de orientada a aspecto, não exclusiva do AspectJ, mas de outras implementações como o JBoss AOP.
Gostaria que os desenvolvedores que conhecem apenas interceptors não pensassem “isso é AOP”. AOP é muito mais do que isso! Leiam o meu artigo dessa edição da MundoJ que acho que ficará claro!
Em relação a entrevista que citou, fui eu quem fez essa entrevista! Um de meus objetivos nesse artigo foi justamente desmistificar os aspectos, mostrando que eles não são assim tão complicados como se pensa!
Legal a discussão. Sou um iniciante em aspectos e vou ler o artigo em breve.
Continuem, pois são nessas listas de fóruns onde se refina mais o conhecimento. Pelo menos comigo, funciona bastante ler os “aspectos” diferentes hahaha.
parabéns pelo Artigo, ele ficou muito bom mesmo.
Me deu uma luz para alguns problemas que não conseguia pensar em uma saída.
Quando comecei a estudar sobre injeção de dependencias achei aquilo essencial, a questão do desacoplamento e do wiring.
O problema é que minhas classes deixaram de ficar acopladas as minhas próprias outras classes e passaram a ficar acopladas a um framework, ou acopladas a uma outra classe minha que encapsulasse a funcionalidade do framework.
Lendo o artigo, percebi então que a injeção de dependencias pode fazer parte de um componente transversal à minha aplicação, certo?
É isso mesmo então? Para deixar minhas classes com um bom nível de desacoplamento devo utilizar a DI juntamente com a AOP?
Pode exemplicar (em palavras mesmo) como seria um jeito de usar isso?
parabéns pelo Artigo, ele ficou muito bom mesmo.
Me deu uma luz para alguns problemas que não conseguia pensar em uma saída.
Quando comecei a estudar sobre injeção de dependencias achei aquilo essencial, a questão do desacoplamento e do wiring.
O problema é que minhas classes deixaram de ficar acopladas as minhas próprias outras classes e passaram a ficar acopladas a um framework, ou acopladas a uma outra classe minha que encapsulasse a funcionalidade do framework.
Lendo o artigo, percebi então que a injeção de dependencias pode fazer parte de um componente transversal à minha aplicação, certo?
É isso mesmo então? Para deixar minhas classes com um bom nível de desacoplamento devo utilizar a DI juntamente com a AOP?
Pode exemplicar (em palavras mesmo) como seria um jeito de usar isso?
Obrigado e mais uma vez, parabéns pelo artigo.[/quote]
O Spring hoje possui suporte a programação orientada a aspectos. Acredito que hoje com as anotaçõe do Spring como @Autowire, você consiga um pouco desse desacoplamento.
Respondendo sua pergunta de forma mais direta: é sim possível interceptar a inicialização da classe com um aspecto para fazer as injeções de dependência, porém isso já tem pronto no Spring de uma forma bem madura!
Recomendo fortemente que você dê uma olhada no artigo que escrevi para a MundoJ 44: “Estratégias para Criação de Objetos Visando Modularidade”. Ele trata bastante sobre essas questões!
A minha grande dúvida sobre a injeção de dependencias é que em algum momento eu vou ter que recuperar um objeto pelo spring.
Em que camada eu vou fazer isso?
a grosso modo, em que lugar que eu devo chamar o getBean() do spring?
Por isso que pensei que pudesse ser um aspecto… Essa chamada.
Na verdade, procure fazer isso apenas com a classe principal da aplicação e nos outros casos use a injeção de dependências do próprio Spring. No caso de aplicações web, os próprios controllers (dependendo do framework q usar) podem já ser criados pelo Spring e receber injeção.
Em todo caso, você pode criar um factory e encapsular o acesso ao Spring através dela.