Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AspectJ + @Configurable

Trying to use both AspectJ and @Configurable with a Spring application.

  • If I load Spring with a @Component annotation on a class, the AspectJ wrapper works and wraps all targeted methods AND the @Autowired annotation causes dependencies to be injected. But the class cannot be instantiated at runtime with the new keyword and have dependencies injected.
  • If I load a @Configurable class without the AspectJ bean, all dependencies are injected correctly on new but none of the methods are proxied through AspectJ.

How can I do both?

Here's my code. Configuration:

@Configuration
@ComponentScan(basePackages="com.example")
@EnableSpringConfigured
@EnableAspectJAutoProxy
@EnableLoadTimeWeaving
public class TestCoreConfig {

    @Bean
    public SecurityAspect generateSecurityAspect(){
        return new SecurityAspect();
    }


    @Bean
    public SampleSecuredClass createSampleClass(){
        return new SampleSecuredClass();
    }
}

Aspect:

@Aspect
public class SecurityAspect {

    @Pointcut("execution(public * *(..))")
    public void publicMethod() {}


    @Around("publicMethod()")
    public boolean test (ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Here!");
        joinPoint.proceed();
        return true;    
    }

}

SampleClass:

//@Configurable
@Component
public class SampleSecuredClass {

    @Autowired
    public SecurityService securityService;

    public boolean hasSecurityService(){
        return securityService != null;
    }

    public boolean returnFalse(){
        return false;
    }
}

And the unit test:

@ContextConfiguration(classes={TestCoreConfig.class})
@RunWith(SpringJUnit4ClassRunner.class)
public class SecurityAspectComponentTest {

    @Autowired
    private SampleSecuredClass sampleSecuredClass;

    @Test
    public void testSecurityRoles(){
        //SampleSecuredClass sampleSecuredClass = new SampleSecuredClass();

        assertTrue("We need to ensure the the @Configurable annotation injected the services correctly", sampleSecuredClass.hasSecurityService());

        assertTrue("We need to ensure the the method has been overwritten", sampleSecuredClass.returnFalse());
    }

}
  • If I get rid of the beans in the TestCoreConfig and create an instance of SampleSecuredClass in the test with new, and change its annotation to @Configurable then the service is injected, but the aspect is not applied.
  • If I run as is here (by injecting the SampleSecuredClass as a bean), then the aspect works and the service is injected, but then all objects have to be created on framework start. I would like to use the @Configurable annotation.
  • If I use both the @Configurable annotation and the Aspect together then I get a illegal type in constant pool error and the context does not start.

Other pieces of information.

  • I have tried a few different java agents--both spring instrumentation and aspectjwrapper. no change.

  • If I include an aop.xml file, then the aspect works but not the @Configurable.

like image 662
Jason Avatar asked Nov 10 '22 04:11

Jason


1 Answers

This seems one of those deep dives sessions into the docs waiting to happen :)

First of all I'd enable debug logging for org.springframework because this will definitely provide some meaningful insight into what and when Spring does...

That being said I believe that your problem lies somewhere in the mist of spring's context lifecycles so I'd check out the docs carefully especially around

  1. Manually specifying that the bean depends on the configuration aspect depends-on="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"

  2. ...or the note around @Configurable(preConstruction=true)

If you want the dependencies to be injected before the constructor bodies execute

  1. ...or @Configurable(autowire=Autowire.BY_NAME,dependencyCheck=true)

Finally you can enable Spring dependency checking for the object references in the newly created and configured object by using the dependencyCheck attribute.

Read the docs carefully, see if and how these hits apply and please let us know the solution you find. It should definitely present itself as a very interesting read.

like image 97
Filip Avatar answered Nov 15 '22 05:11

Filip