starter example java spring aspectj spring-aop

java - example - spring-aop maven



Autoincronización de primavera con @Configurable (10)

Además, verifique que su versión de AspectJ esté actualizada. Perdí unas horas tratando de hacer que esto funcionara, y la causa era una versión anterior de Aspectjweaver.jar. Actualicé a 1.7.2 y todo funcionó a las mil maravillas.

Estoy jugando con la idea de usar Spring @Configurable y @Autowire para inyectar DAO en objetos de dominio para que no necesiten conocimiento directo de la capa de persistencia.

Intento seguir http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-atconfigurable , pero mi código parece no tener ningún efecto.

Básicamente, tengo:

@Configurable public class Artist { @Autowired private ArtistDAO artistDao; public void setArtistDao(ArtistDAO artistDao) { this.artistDao = artistDao; } public void save() { artistDao.save(this); } }

Y:

public interface ArtistDAO { public void save(Artist artist); }

y

@Component public class ArtistDAOImpl implements ArtistDAO { @Override public void save(Artist artist) { System.out.println("saving"); } }

En application-context.xml, tengo:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springsource.org/dtd/spring-beans-2.0.dtd"> <beans> <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" /> <bean class="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect" factory-method="aspectOf"/> </beans>

La exploración e inicialización de la ruta de clase se realiza mediante el módulo de resorte para Play! marco, aunque funcionan otros beans autoconectados, así que estoy bastante seguro de que esta no es la causa raíz. Estoy usando Spring 3.0.5.

En otro código (dentro de un método en Bean que se inyecta en mi controlador usando Spring, de hecho), estoy haciendo esto:

Artist artist = new Artist(); artist.save();

Esto me da una NullPointerException que intenta acceder al artista Dao en Artist.save ().

¿Alguna idea de lo que estoy haciendo mal?

Martín


Debería ver cómo lo hace Spring Roo , ya que hace exactamente lo que quiere hacer.

Hay muchas cosas que pueden causar que tenga la NPE, pero la mayoría de las veces tiene que ver con no compilar correctamente con el compilador AspectJ y sin tener el jar de Aspectos de primavera en su ruta de acceso de AspectJ lib (esto es diferente de su ruta de clase).

Primero, intente que funcione con Maven y el plugin de compilador AspectJ. Es por eso que recomiendo Spring Roo, ya que generará un archivo POM con la configuración correcta.

He encontrado que @Configurable realmente no funciona con LTW (a pesar de que una de las respuestas lo dice). Necesitará tiempo de compilación para que @Configurable funcione, ya que el consejo está sucediendo en el momento de la construcción del objeto (no se puede hacer el asesoramiento del constructor con Springs LTW).


Estaba teniendo este problema con Tomcat 7 usando LTW tratando de autoautar beans en mis clases de dominio.

Hubo algunas actualizaciones del documento para 3.2.x en http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-configurable-container que reveló que uno puede usar @EnableSpringConfigured en lugar de la configuración xml.

Así que tengo la siguiente anotación en mi objeto de dominio:

@Configurable(preConstruction=true,dependencyCheck=true,autowire=Autowire.BY_TYPE) @EnableSpringConfigured

@EnableSpringConfigured es un sustituto de

<context:spring-configured />

y no olvide agregar esto a su archivo xml de contexto:

<context:load-time-weaver weaver-class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver" aspectj-weaving="on"/>

Por supuesto que necesitaba configurar Tomcat para el tiempo de carga tejiendo primero.

Además, me encontré con un error en 3.2.0 (puntero nulo), así que necesitaba actualizar a Spring 3.2.1 ( https://jira.springsource.org/browse/SPR-10108 )

¡Todo está bien ahora!



Primero, habilite el registro de depuración de Spring. Yo uso Log4j para hacerlo. Creé un registrador como ese (con la configuración Log4j xml para poder usar RollingFileAppender):

<log4j:configuration> <appender name="roll" class="org.apache.log4j.rolling.RollingFileAppender"> blah blah configuration blah blah </appender> <logger name="org.springframework"> <level value="debug" /> <appender-ref ref="roll" /> </logger> </log4j:configuration>

Esto te permitirá ver lo que Spring está haciendo y cuándo.

En segundo lugar, tiene ArtistDAO conectado automáticamente pero no veo dónde tiene un bean llamado ArtistDAO. Su bean componente DAO se llamará "artistDaoImpl" por defecto. Intenta cambiar @Component por @Component("artistDao") y aplica @Autowired al setter en su lugar:

private ArtistDAO artistDao; @Autowired public void setArtistDao(ArtistDAO artistDao) { this.artistDao = artistDao; }


Tal vez usar la anotación @Repository para el DAO lo hará.


Tuve el mismo problema y nunca logré que el código funcionara con @Configurable y @Autowired. Finalmente decidí escribir un aspecto yo mismo que manejaría las anotaciones @Configurable y @Autowired. Aquí está el código:

import java.lang.annotation.Annotation; import java.lang.reflect.Field; import org.apache.log4j.Logger; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @SuppressWarnings( "rawtypes" ) @Aspect public class AutoInjectDependecyAspect implements ApplicationContextAware { private static final Logger LOGGER = Logger.getLogger( AutoInjectDependecyAspect.class ); private ApplicationContext applicationContext = null; @Pointcut( "execution( (@org.springframework.beans.factory.annotation.Configurable *).new())" ) public void constructor() { } @Before( "constructor()" ) public void injectAutoWiredFields( JoinPoint aPoint ) { Class theClass = aPoint.getTarget().getClass(); try{ Field[] theFields = theClass.getDeclaredFields(); for ( Field thefield : theFields ) { for ( Annotation theAnnotation : thefield.getAnnotations() ) { if ( theAnnotation instanceof Autowired ) { // found a field annotated with ''AutoWired'' if ( !thefield.isAccessible() ) { thefield.setAccessible( true ); } Object theBean = applicationContext.getBean( thefield.getType() ); if ( theBean != null ) { thefield.set( aPoint.getTarget(), theBean ); } } } } } catch ( Exception e ) { LOGGER.error( "An error occured while trying to inject bean on mapper ''" + aPoint.getTarget().getClass() + "''", e ); } } @Override public void setApplicationContext( ApplicationContext aApplicationContext ) throws BeansException { applicationContext = aApplicationContext; } }

A continuación, en su contexto de primavera, defina el aspecto para que el contexto de primavera se inyecte en el aspecto

<bean class="[package_name].AutoInjectDependecyAspect" factory-method="aspectOf"/>


Tuve un problema similar que resolví hoy. Lo importante es que debe habilitar el entrelazado en tiempo de carga y asegurarse de que se carguen las clases aspectj apropiadas. En tu pom.xml necesitas agregar el artefacto aspectjweaver :

... <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.12</version> </dependency> ....

Puede cambiar la versión si lo necesita. Luego, iría a la ruta xsd en su aplicación-contexto.xml en lugar de la ruta DTD:

<?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: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-3.0.xsd"> <!--Scans the classpath for annotated components @Component, @Repository, @Service, and @Controller --> <context:component-scan base-package="your.base.package"/> <!--Activates @Required, @Autowired, @PostConstruct, @PreDestroy and @Resource --> <context:annotation-config/> <!--This switches on the load-time weaving for @Configurable annotated classes --> <context:load-time-weaver/> </beans>


try: @Configurable (autowire = Autowire.BY_TYPE). Autowired está predeterminado en off: <