Autowire working in unit test but not in main java class - spring

I've a domain class that I want to auto-populate from external config. Here is my domain class:
#Data
#Configuration
#PropertySource("classpath:application.properties")
public class StudioVo {
#Value("${studio.code}")
private code;
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Here is my context xml:
<bean class="org.springframework.batch.core.scope.StepScope" />
<bean id="ItemReader" class="com.sdm.studio.reader.StudioReader" scope="step">
<property name="studioVo" ref="StudioVo" />
</bean>
<bean id="StudioConfigVo" class="com.sdm.studio.domain.StudioVo" />
</bean>
Here is the class where I want to use the vo:
#Slf4j
#Data
public class StudioReader implements ItemReader<List<Studio>> {
private StudioVo studioVo;
public List<Studio> read() throws Exception {
System.out.println("getCode: " + studioVo.getCode()); //code is null here
return null;
}
}
However when I run it via unit test by autowiring, it runs fine. Like this:
#RunWith(SpringRunner.class)
#SpringBootTest
public class StudioTest {
#Autowired
private StudioVo studioVo;
#Test
public void testAutoPopulationOfStudio(){
System.out.println("getCode: "+ studioVo.getCode()); // works!
// Assert.assertTrue(studioVo.getCode().equals("102"));
}
}
Not sure what's going on here - I'm working with an old Spring Batch application wrapped in Spring Boot (so there is a mix of XML based and Java based config - and may be that is the cause of this issue). What am I missing?

In your StudioTest, you are autowiring StudioReader where as you missed the #Autowired in your StudioReader code, so add it as shown below:
#Slf4j
#Data
public class StudioReader implements ItemReader<List<Studio>> {
#Autowired //add this so that studioVo can be injected
private StudioVo studioVo;
//add other code
}

Please be certain to note that using #Autowire requires a chain of Spring-managed beans below it from wherever you are using it including the class in which you are using #Autowire. That is because Spring needs the precedent references to match up the object-reference hierarchy. I.e., in business logic layer ClassA, you want to #Autowire a field. ClassA itself needs to be a managed bean. Further, if the field you want to #Autowire holds an object that has referential dependencies to other objects (and most do), these also must be Spring-managed.
For example, the following will work:
package com.example.demo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MessageRunner {
private static SetterMessage setterMessage;
public static void main(String[] args) {
setterMessage = (SetterMessage) (new AnnotationConfigApplicationContext(DemoConfiguration.class)).getBean("setterMessage");
setterMessage.setMessage("Finally it works.");
p(setterMessage.getMessage());
}
private static void p(String s) {
System.out.println(s);
}
}
DemoConfiguration.java looks like this:
package com.example.demo;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan(basePackages = "com.example.demo")
public class DemoConfiguration {
}
SetterMessage.java, this:
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
#Service
#Scope("prototype")
public class SetterMessage {
private String message = null;
#Autowired
private SetterMessage2 setterMessage2;
public String getMessage(){
return message+setterMessage2.getSubMessage();
}
public void setMessage(String message) {
this.message = message;
setterMessage2.setSubMessage("("+message+")");
}
}
SetterMessage2.java:
package com.example.demo;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
#Service
#Scope("prototype")
public class SetterMessage2 {
private String subMsg = "";
public void setSubMessage(String msg) {
subMsg = msg;
}
public String getSubMessage() {
return subMsg;
}
}
Note that SetterMessage2.java is annotated as a Component (#Service) but no field in it is autowired. That is because it's the end of the object reference chain. But because it is a Component, it can be autowired into SetterMessage.java. However look at MessageRunner.java's main() method and field declarations. Note that the class field SetterMessage is NOT autowired. If it were annotated as #Autowired, main() would fail at runtime, throwing an NPE with the reference to setterMessage in main(). This is because MessageRunner.java is not marked as some kind of component. So we need to grab a valid instance of MessageSetter from the application context and use it.
To emphasize, the following version of MessageRunner.java's main() method WILL FAIL, throwing an NPE, if MessageRunner.java looked like this:
...
public class MessageRunner {
#Autowired // <-- This will not do the job for us
private static SetterMessage setterMessage;
public static void main(String[] args) {
setterMessage.setMessage("Finally it works."); // NPE here on ref to setterMessage
p(setterMessage.getMessage());
}
...
This is a real gotchya for people new to Spring. In fact, I'd place it among the Top Five Spring Newbie Discouragers and a really evil, pernicious detail that has caused new Spring programmers countless hours in aggravation and Google searches. So I do hope that noting this phenom here will save at least some newbies time and high blood pressure spikes.
Note: If you go to create the above classes in your IDE, bear in mind these were developed with Spring Boot enabled.

Related

Spring boot get #value within a class extending a dependency

Folks, am trying to access config properties from within a class that I've extended from a dependency. Apparently the config class is returning a null pointer in my implementation class (CustomUtil).
pom.xml
...
<dependency>
<groupId>com.utilapp</groupId> //3rd party library that I need to use
<artifactId>util-lib</artifactId>
</dependency>
...
The BaseUtil is from the dependency. CustomUtil is a bean in my SpringBoot App & am overriding the method as below to check the key from the config property ignoreKeyList .
package com.myapp
...
#Component
public class CustomUtil extends BaseUtil {
#Autowired
private ClientConfig clientConfig; // This returns null!
#Override
protected boolean shouldExcludeFromList(String key) {
return this.clientConfig.getIgnoreKeyList.contains(key); // their library/util excludes certain keywords from the content being formatted
}
}
Config class in my SpringBoot App.
package com.myapp
...
#Configuration
#Getter
#Setter
public class ClientConfig {
#Value("${myapp.ignorekeys}")
private List<String> ignoreKeyList;
...
...
}
Main class in my app.
package com.myapp
...
#SpringBootApplication
public class MyClientApplication {
public static void main(String[] args) {
SpringApplication.run(MyClientApplication.class, args);
}
}
Service implementation class in my SpringBoot App.
package com.myapp
import com.utilapp.formatters.FormatBuilder;
import com.utilapp.formatters.TextFormatter;
...
#Service
public class ServiceImpl implements MyService {
#Autowired
private ClientConfig clientConfig; // works here!
public String formatContent(String content) {
TextFormatter formatter = this.getTextFormatter();
return formatter.parseAndFormat(content);
}
private TextFormatter getTextFormatter() {
return FormatBuilder.custom() // FormatBuilder is from the dependency
.withApplication(this.clientConfig.getAppName()) // In their library, the BaseUtil gets instantiated which am extending in my CustomUtil bean
...
...
.withIndentSupport(Boolean.TRUE)
.build();
}
}
Controller in my app
package com.myapp
...
#RestController
#RequestMapping("/app/v1")
public class StyleController {
#Autowired
private MyService myService;
#GetMapping("/format")
public String formatContent(#RequestParam String content) {
return this.myService.formatContent(content);
}
}
When I debug ClientConfig, it loads the properties from the config file; application.properties in src\main\resources.
But for some reason the ClientConfig is returning null from within the CustomUtil bean. Not sure why!
I originally thought it was due to ordering of bean instantiation. I tried playing around with #Order, #DependsOn, #ComponentScan, #ScanBasePackages etc, but none yields.
Any pointers/guidance please.
Thanks.

Pointcut expression not matching the Spring Data method despite specfying exact name in expression

In my Spring Boot project, I have AddressRepository that brings all addresses from Database. I have an Aspect class and a pointcut expression that executes after the findAll() method called. When I execute my test case, the Advice is not being triggered and other methods like findAll(Sort sort), findAll(Pageable pageable) work just fine. I am not sure if this is a bug with Spring Boot or my expression. I tried with Spring Boot 2.0.5 and 2.1.0, nothing seemed to solve my problem
AddressLogging.java
#Aspect
#Configuration
public class AddressLogging {
private Logger log=LoggerFactory.getLogger(AddressLogging.class);
//#Pointcut("execution(* com.springtesting.repo.AddressRepository.*(..))")
#Pointcut("execution(* com.springtesting.repo.AddressRepository.findAll())")
public void getAddresses() {}
#After("getAddresses()")
public void afterAdvice() {
log.error("Log Message: Inside afterAdvice() advice");
}
}
AopTest.java
#RunWith(SpringRunner.class)
#SpringBootTest
public class AopTest {
#Autowired
private AddressRepository addressRepository;
#Test
public void getAddresses() {
//addressRepository.findAll(PageRequest.of(0,20, Sort.by("id")));
addressRepository.findAll();
}
#Test
public void findAddressById() {
addressRepository.findById(1L);
}
}
AddressRepository
public interface AddressRepository extends JpaRepository<Address,Long> {}
A Spring AOP aspect should also be a #Component and be picked up by component scan. I have no idea why you added #Configuration to the aspect instead because there is no configuration here.
Maybe your test of a separate configuration class should bear the #Configuration annotation and you should also activate something like #EnableAspectJAutoProxy(proxyTargetClass = true) and #ComponentScan(basePackages = { "de.scrum_master" }).
Here is a snippet from one of my Spring AOP playground projects (I hardly use it, I don't use Spring AOP or even Spring itself, usually I use the more powerful AspectJ:
package de.scrum_master.app;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
#Configuration
#EnableAspectJAutoProxy(proxyTargetClass = true)
#ComponentScan(basePackages = { "de.scrum_master" })
public class Application2 {
public static void main(String[] args) throws Exception {
ApplicationContext appContext = new AnnotationConfigApplicationContext(Application2.class);
B b = (B) appContext.getBean("b");
System.out.println(b.getData("bbb"));
A a = (A) appContext.getBean("b");
System.out.println(a.getData("aaa"));
}
}

Should Mockito be used with MockMvc's webAppContextSetup in Spring 4?

I'm having difficulties getting Mockito and MockMvc working together when I use the webAppContextSetup together. I'm curious if it's because I'm mixing the two in a way they were never intended.
Source: https://github.com/zgardner/spring-boot-intro/blob/master/src/test/java/com/zgardner/springBootIntro/controller/PersonControllerTest.java
Here is the test I'm running:
package com.zgardner.springBootIntro.controller;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static java.lang.Math.toIntExact;
import static org.hamcrest.Matchers.is;
import static org.mockito.MockitoAnnotations.initMocks;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
import com.zgardner.springBootIntro.Application;
import com.zgardner.springBootIntro.service.PersonService;
import com.zgardner.springBootIntro.model.PersonModel;
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
public class PersonControllerTest {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext webApplicationContext;
#Autowired
private DefaultListableBeanFactory beanFactory;
#Mock
private PersonService personService;
#InjectMocks
private PersonController personController;
#Before
public void setup() {
initMocks(this);
// beanFactory.destroySingleton("personController");
// beanFactory.registerSingleton("personController", personController);
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
#Test
public void getPersonById() throws Exception {
Long id = 999L;
String name = "Person name";
when(personService.findById(id)).thenReturn(new PersonModel(id, name));
mockMvc.perform(get("/person/getPersonById/" + id))
.andDo(print())
.andExpect(jsonPath("$.id", is(toIntExact(id))))
.andExpect(jsonPath("$.name", is(name)));
}
}
I was expecting that when mockMvc performed the mock of that HTTP call, it would use the PersonController I defined in my test. But when I debug through, it's using the PersonController which was created by the SpringJunit4ClassRunner on the test boot up.
I found two ways to get this to work:
Inject the bean factory, remove the old personController singleton, and add my own. This is ugly, and I am not a fan.
Wire everything up using the standaloneSetup instead of webAppContextSetup. I may do this instead as I don't have to touch the bean factory.
Here are some different articles I've found that somewhat touch on the topic:
Spring Tutorial - Building REST Services This just autowires in the repos to clear out the data before the integration test takes place.
Use Spring MVC Test framework and Mockito to test controllers This uses Mockito along with webAppContextSetup, but this is in Spring 3. (I'm using Spring Boot)
Unable to mock Service class in Spring MVC Controller tests This uses the standaloneSetup, which does work in my case too.
Thoughts?
You might be interested in the new testing features coming in Spring Boot 1.4 (specifically the new #MockBean annotation). This sample shows how a service can be mocked and used with a controller test.
For some reason the Mockito annotations #Mock et #InjectMocks won't work in this case.
Here's how I managed to make it work :
Instantiate the personService bean manually using your own Test context
make Mockito create a mock for this personService.
let Spring inject these mocks in the controller PersonController.
You should have your TestConfig :
#Configuration
public class ControllerTestConfig {
#Bean
PersonService personService() {
return mock(PersonService.class);
}
}
In your PersonControllerTest, you won't need the personController anymore, since it's managed by the mockMvc through the perform method. You also don't need to execute initMocks() because you initialize your mocks manually inside the Spring config. You should have something like :
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = {Application.class, ControllerTestConfig.class})
#WebAppConfiguration
public class PersonControllerTest {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext webApplicationContext;
#Autowired
PersonService personService;
#Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
#Test
public void getPersonById() throws Exception {
Long id = 999L;
String name = "Person name";
when(personService.findById(id)).thenReturn(new PersonModel(id, name));
mockMvc.perform(get("/person/getPersonById/" + id))
.andDo(print())
.andExpect(jsonPath("$.id", is(toIntExact(id))))
.andExpect(jsonPath("$.name", is(name)));
}
}
I sometimes use Mockito to fake Spring beans with usage of #Primary and #Profile annotations. I wrote a blog post about this technique. It also contains link to fully working example hosted on GitHub.
To extend florent's solution, I encountered performance issues and extensibility issues creating separate configurations for every controller test which needed a different set of service mocks. So instead, I was able to mock out my application's service layer by implementing a BeanPostProcessor alongside my tests which replaces all #Service classes with mocks:
#Component
#Profile("mockService")
public class AbcServiceMocker implements BeanPostProcessor {
private static final String ABC_PACKAGE = "com.mycompany.abc";
#Override
public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
if (StringUtils.startsWith(bean.getClass().getPackage().getName(), ABC_PACKAGE)) {
if (AnnotationUtils.isAnnotationDeclaredLocally(Service.class, bean.getClass())
|| AnnotationUtils.isAnnotationInherited(Service.class, bean.getClass())) {
return mock(bean.getClass());
}
}
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
return bean;
}
}
I enabled these mocks in specific tests with an #ActiveProfiles annotation:
#WebAppConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({"classpath:/WEB-INF/application-context.xml"})
#ActiveProfiles("mockService")
public class AbcControllerTest {
private MockMvc mvc;
#Before
public final void testBaseSetup() {
mvc = MockMvcBuilders.webAppContextSetup(context).build();
}
Lastly, the injected Mockito mocks were wrapped in an AopProxy causing Mockito's expect and verify calls to fail. So I wrote a utility method to unwrap them:
#SuppressWarnings("unchecked")
protected <T> T mockBean(Class<T> requiredType) {
T s = context.getBean(requiredType);
if (AopUtils.isAopProxy(s) && s instanceof Advised) {
TargetSource targetSource = ((Advised) s).getTargetSource();
try {
return (T) targetSource.getTarget();
} catch (Exception e) {
throw new RuntimeException("Error resolving target", e);
}
}
Mockito.reset(s);
return s;
}

Spring annotations - #Configuration to invoke spring bean auto-building

If I declare a class using #Bean and then component scan for the class, spring will instantiate the class by invoking it's constructor and injecting constructor args and injecting any fields marked with #Inject. For simplicity's sake, lets call this spring auto-building.
I dislike component scan and wish to avoid it completely (I don't wish to discuss my reasons for not liking it). I would like to use a #Configuration object instead but would still like to have the auto-building functionality available to me. Is it possible to invoke spring to auto-build my objects instead of explicitly having to pass all the constructor arguments in my #Configuration object?
Lets assume that I have a bean:
public class MyServiceImpl implements MyService {
public MyServiceImpl(Dependency1 d1, Dependency d2) { ... }
....
}
I could define a configuration object like this:
#Configuration
public class MyConfiguration {
// lets assume d1 and d2 are defined in another #Configuration
#Inject
Dependency1 d1;
#Inject
Dependency2 d2;
#Bean
public MyService myService() {
// I dislike how I have to explicitly call the constructor here
return new MyServiceImpl(d1, d2);
}
}
But now, I have explicitly had to call the MyServiceImpl constructor myself so I will have to keep updating this as my constructor changes over time.
I was hoping that I could declare an abstract method so that spring auto-building could take place:
#Configuration
public abstract class MyConfiguration {
#Bean
public abstract MyServiceImpl myService();
}
But this doesn't work. Is there a way that I can invoke spring auto-building without using a component scan?
In Google Guice, this can be done via the Binder:
https://google-guice.googlecode.com/svn/trunk/javadoc/com/google/inject/Binder.html
In Tapestry IOC, this can be done via the ServiceBinder:
http://tapestry.apache.org/ioc-cookbook-basic-services-and-injection.html#IoCCookbook-BasicServicesandInjection-SimpleServices
Update
Based on spod's answer, I was able to achieve what I was after (thanks!). Test case included for anyone that wants to do the same:
import java.util.Date;
import javax.inject.Inject;
import junit.framework.Assert;
import org.junit.Test;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
public class AutoBuildConfigurationTest {
#Configuration
public static class MyConfiguration {
#Inject
private AutowireCapableBeanFactory beanFactory;
#Bean
public Date date() {
return new Date(12345);
}
#Bean
public MyService myService() {
return autoBuild(MyService.class);
}
protected <T> T autoBuild(Class<T> type) {
return type.cast(beanFactory.createBean(type, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, true));
}
}
public static class MyService {
private Date date;
public MyService(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
}
#Test
public void testAutoBuild() {
ApplicationContext appContext = new AnnotationConfigApplicationContext(MyConfiguration.class);
MyService myService = appContext.getBean(MyService.class);
Assert.assertEquals(12345, myService.getDate().getTime());
}
}
The java based container configuration doesnt depend on doing a component scan in any way. Its merely a different approach for the XML based component configuration. With the XML configuration you'd just have to declare your bean with the MyServiceImpl class in case its already #inject annotated. Spring would recognize the annotations and take care of them. If you really want to instanciate MyServiceImpl from a #Configuration java class without calling the constructor yourself, then you'd have to make use of the bean factory (havent tested it, just give it a try):
#Configuration
public class MyConfiguration {
#Autowired AutowireCapableBeanFactory beanFactory;
#Bean public MyService myService() {
return beanFactory.createBean(MyServiceImpl.class, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, true);
}
}

How should aspect weaving be limited to classes referenced by aop:advisor pointcuts?

I'm trying to trace execution of an app running on ServiceMix 3.2 which uses spring 2.5 under the hood. I'm using CGLIB (advising classes, not interfaces) and I would like to direct tracing using pointcuts. I therefore configured spring to perform load-time weaving in one of my service unit xbean.xml files like so:
<bean id="debugInterceptor"
class="org.springframework.aop.interceptor.SimpleTraceInterceptor"/>
<aop:config proxy-target-class="true">
<aop:advisor advice-ref="debugInterceptor"
pointcut="within(my.package.AClass)" order="1"/>
</aop:config>
Classes get advised, but it isn't limited to what I specified in the pointcut, i.e. methods of classes other than my.package.AClass get advised and, for reasons not important here, break class loading.
I tried defining the pointcut this way, but it made no difference:
<aop:advisor advice-ref="debugInterceptor"
pointcut="execution(* my.package.AClass.*(..))" order="1"/>
In general, I would like to advise my.package..* classes except my.package.no_aop.*, but I don't seem to be making progress.
Why does CGLIB process classes outside of my.package.AClass? How do I prevent it? Would switching to Spring AOP (as opposed to AspectJ) make a difference?
I did it using Spring 3.0.x and #AspectJ annotations, but it should be analogous using 2.5 and XML.
Class A from package my.pkg, that needs to be adviced:
package my.pkg;
public class ClassA {
public void doFromClassA() {
System.out.println("Hello from A!");
}
}
Class B from package my.pkg.noaop, that needs not to be adviced:
package my.pkg.noaop;
public class ClassB {
public void doFromClassB() {
System.out.println("Hello from B!");
}
}
The aspect:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
#Aspect
public class AopTestAspect {
#Around("within(my.pkg..*) && !within(my.pkg.noaop..*)")
public void advice(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("Hello from adviced!");
pjp.proceed();
}
}
The configuration (let me know if You need XML version):
import my.pkg.ClassA;
import my.pkg.noaop.ClassB;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class AopTestConfig {
#Bean
public ClassA classA() {
return new ClassA();
}
#Bean
public ClassB classB() {
return new ClassB();
}
#Bean
public AopTestAspect aspect() {
return new AopTestAspect();
}
#Bean
public AnnotationAwareAspectJAutoProxyCreator autoProxyCreator() {
AnnotationAwareAspectJAutoProxyCreator autoProxyCreator = new AnnotationAwareAspectJAutoProxyCreator();
autoProxyCreator.setProxyTargetClass(true);
return autoProxyCreator;
}
}
The test:
import my.pkg.ClassA;
import my.pkg.noaop.ClassB;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class AopTest {
#Test
public void test() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AopTestConfig.class);
applicationContext.refresh();
ClassA a = BeanFactoryUtils.beanOfType(applicationContext, ClassA.class);
ClassB b = BeanFactoryUtils.beanOfType(applicationContext, ClassB.class);
a.doFromClassA();
b.doFromClassB();
}
}
And the output from the test:
Hello from adviced!
Hello from A!
Hello from B!
As You can see only the ClassA got adviced.
Conclusion
The key is the pointcut experssion:
within(my.pkg..*) && !within(my.pkg.noaop..*)

Resources