Java aop ComponentScan not working & AnnotationConfigApplicationContext getBean not working - java

I wrote a simple set of classes to show a friend about using Annotations for AOP (instead of xml config) . We couldnt get the #ComponentScan to work AND AnnotationConfigApplicationContext getBean too misbehaves. I wanted to understand two things . See Code below :
PersonOperationsI.java
package samples.chapter3;
import org.springframework.stereotype.Component;
#Component
public interface PersonOperationsI {
public String getName();
}
PersonOperations.java
/**
*
*/
package samples.chapter3;
import org.springframework.stereotype.Component;
#Component
public class PersonOperations implements PersonOperationsI {
public String getName() {
return "";
}
}
PersonOperationsConfigClass.java
package samples.chapter3;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
#Configuration
//question2 - Below Component Scan didnt work - Test Case failing in setup()
//#ComponentScan(basePackages = {"samples.chapter3"})
#EnableAspectJAutoProxy
public class PersonOperationsConfigClass {
}
PersonOperationsAdvice.java
/**
*
*/
package samples.chapter3;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
#Component
#Aspect
public class PersonOperationsAdvice {
/**
* execution( [Modifiers] [ReturnType] [FullClassName].[MethodName]
([Arguments]) throws [ExceptionType])
* #param joinPoint
* #return
*/
#Before("execution(public * samples.chapter3.PersonOperations.getName()))")
public String beforeGetName(JoinPoint joinPoint) {
System.out.println("method name = " + joinPoint.getSignature().getName());
return null;
}
}
PersonOperationsTest.java
package samples.chapter3;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = { PersonOperationsConfigClass.class })
public class PersonOperationsTest {
//#Autowired
private PersonOperationsI obj;
#Before
public void setUp() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("samples.chapter3");
ctx.refresh();
obj = ctx.getBean(PersonOperationsI.class);
//obj = ctx.getBean(PersonOperations.class);//getBean of Child class not working - why ?
Assert.assertNotNull(obj);
ctx.close();
}
#Test
public void test() {
System.out.println(obj.getName());
}
}
Question1 - Why #componentscan doesnt work .If I dont use AnnotationConfigApplicationContext in test case and just rely on #componentscan & autowired - the object in test case is null
Question2 - ctx.getBean(PersonOperations.class);//getBean of Child class not working - why ?

A1 , #ComponentScan didn't work because it is commented out from the "The component classes to use for loading an ApplicationContext." or PersonOperationsConfigClass
#Configuration
//#ComponentScan(basePackages = {"samples.chapter3"})
#EnableAspectJAutoProxy
public class PersonOperationsConfigClass {}
The test class gets the ApplicationContext created from the component classes specified with the #ContextConfiguration annotation. Since no components were created or auto detected , #Autowired failed.
When AnnotationConfigApplicationContext was used within a method annotated with #Before , an ApplicationContext was programmatically created.ctx.scan("samples.chapter3"); scanned and auto-deteced PersonOperations annotated with #Component. obj reference got set with the code obj = ctx.getBean(PersonOperationsI.class);. This object was not 'Autowired'.
Update based on the comment from OP
The Junit 4 annotations and the #ExtendWith(SpringExtension.class) combination is not working for me.
Following Test class runs successfully with zero errors/failures. obj is autowired and not null. I have used the corresponding annotations from Junit 5.
package rg.app.aop.so.q1;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes= {PersonOperationsConfigClass.class})
public class PersonOperationsTest {
#Autowired
private PersonOperationsI obj;
#BeforeEach
public void setUp() {
System.out.println("init ::"+ obj);
Assertions.assertNotNull(obj);
}
#Test
public void testPersonOps() {
Assertions.assertNotNull(obj);
}
}
Configuration class
package rg.app.aop.so.q1;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
#Configuration
#EnableAspectJAutoProxy
#ComponentScan(basePackages = {"rg.app.aop.so.q1"})
public class PersonOperationsConfigClass {
}
A2,
Following are my analysis.
Remember , #EnableAspectJAutoProxy has got a default value "false" for proxyTargetClass attribute. This attribute determines the proxying mechanism : JDK proxy (false) or CGLIB proxy (true) .
Here the presence of a valid Aspect with a valid advice results in the actual proxying to kick in. A component will get proxied only when the advice has any effect on it. In short , the proxying of a Component happens only if required.
Case 1
When : #EnableAspectJAutoProxy / #EnableAspectJAutoProxy(proxyTargetClass = false )
ctx.getBean(InterfaceType) returns a bean
ctx.getBean(ImplementationClassType) fails to return a bean
Case 2
When : #EnableAspectJAutoProxy(proxyTargetClass = true )
ctx.getBean(InterfaceType) returns a bean
ctx.getBean(ImplementationClassType) returns a bean
Case 3
When : #EnableAspectJAutoProxy annotation is absent
ctx.getBean(InterfaceType) returns a bean
ctx.getBean(ImplementationClassType) returns a bean
Case 1 , Spring AOP is enabled with proxyTargetClass as false. JDK proxy creates a proxy bean of Interface type.
The bean created is of type InterfaceType and not ImplementationClassType . This explains why ctx.getBean(ImplementationClassType) fails to return a bean.
Case 2 , Spring AOP is enabled with proxyTargetClass as true . CGLIB creates a proxy bean by subclassing the class annotated with #Component.
The bean created is of type ImplementationClassType , as well qualifies as InterfaceType. So both the getBean() calls returns this bean successfully.
Case 3,
Spring only create "proxy" objects if any special processing is required ( eg: AOP , Transaction Management ).
Now with this logic , since #EnableAspectJAutoProxy is absent , a bean gets created for class annotated with #Component without any proxying.
The bean created is of type ImplementationClassType , as well qualifies as InterfaceType. So both the getBean() calls returns this bean successfully.
Analysis done with the following code.
package rg.app.aop.so.q1;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class AppMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("rg.app.aop.so.q1");
ctx.refresh();
System.out.println();
for(String name:ctx.getBeanNamesForType(PersonOperationsI.class)) {
System.out.println(name);
}
for(String name:ctx.getBeanNamesForType(PersonOperations.class)) {
System.out.println(name);
}
PersonOperationsI obj = ctx.getBean(PersonOperationsI.class);
System.out.println(obj.getClass());
obj = ctx.getBean(PersonOperations.class);
System.out.println(obj.getClass());
ctx.registerShutdownHook();
}
}
Case 1 prints
personOperations
class com.sun.proxy.$Proxy18
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'rg.app.aop.so.q1.PersonOperations' available
Case 2 prints
personOperations
personOperations
class rg.app.aop.so.q1.PersonOperations$$EnhancerBySpringCGLIB$$c179e7f2
class rg.app.aop.so.q1.PersonOperations$$EnhancerBySpringCGLIB$$c179e7f2
Case 3 prints
personOperations
personOperations
class rg.app.aop.so.q1.PersonOperations
class rg.app.aop.so.q1.PersonOperations
Hope this helps

Usually you should use #ComponentScan along with a #Configuration annotated class and keep in mind that #ComponentScan without arguments tells Spring to scan the current package and all of its sub-packages..
The #Component class tells Spring to create a bean of that type so you no longer need to use xml configuration, and the bean is a class that can be instantiated => no interface / abstract classes. So, in your case, you should remove the #Component from PersonOperationsI and leave it only in PersonOperations. When you annotate a class with #Component, the default name given to the bean is the class name with lower first letter, so you should call ctx.getBean("personOperationsI") or ctx.getBean(PersonOperations.class)
And for the future read these naming conventions for interfaces and implementations. In your case I would modify the following :
PersonOperationsI to Operations

Question 2
As you said, bean scanning process was not complete, so there is no bean in context and you should not expect any bean from context, Either #Autowired way or context.getBean way.(Both ways return null )
Below link has more information on bean scanning(It may help)
Spring Component Scanning

Related

How to solve Unsatisfied Dependency Exception? Problem with Annotation Qualifiers

I trying to implemet a singleton design pattern in Spring. I am running in an error wwhen running my code.
my configuration file is:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan("springdemo3")
public class AppConfig {
}
I have created a service interface as follow:
package springdemo3;
public interface Service {
void doSomething();
}
I have created interface called Pump as follow;
public interface Pump {
void features();
}
Created two types of pumps electric and water pump both implementing pump interface, as follow:
package springdemo3;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
#Component
public class ElectricPump implements Pump{
#Override
#Primary
public void features() {
System.out.println("This pump is an "
+ "electric pump");
}
}
package springdemo3;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
#Component
public class WaterPump implements Pump{
#Override
public void features() {
System.out.println("This pump is pumping"
+ " water");
}
}
My serviceB bean is created as follow:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
#Component //This is a bean
public class ServiceB implements Service{
#Autowired
#Qualifier("electricpump")
private Pump mPump;
public Pump getMpump() {
return mPump;
}
public void setMpump(Pump mPump) {
this.mPump = mPump;
}
public void doSomething() {
System.out.println("We have a water"
+ " pump running here");
mPump.features();
}
}
While my main function is as follow:
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/*** Here I'm not using XML configuration and using Singleton Design Pattern */
public class SpringDemo3 {
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
ServiceB mServiceB = context.getBean(ServiceB.class);
mServiceB.doSomething();
}
}
When I run it, I get the following error:
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'serviceB': Unsatisfied dependency expressed through field 'mPump'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'springdemo3.Pump' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier("electricpump")}
I'm trying to understand Spring Framework. Please note all these classes are in the same package. What is it that I'm doing wrong here?
But this worked
Please bear in mind that default naming convetion for spring beans is camel case, so in fact the proper name for your bean should be electricPump instead of electricpump. Then, you should be able to autowire the bean.
Other than that, field autowiring is not recommended as it makes unit testing of your service more difficult. Use constructor autowiring preferably.
Also, you've placed #Primary in the incorrect position, as it is the annotation which marks the bean to be the first preference for autowiring. It can be used on method level but it only makes sense when the method is defining a bean and is annotated with #Bean annotation as well.
As mentioned in my comment #Qualifier("electricpump") needed a capital P for Pump.
I created a branch and made a pull request to your project:
Restructured your project
Added a maven pom.xml (because I couldn't run your project)
Fixed the bean name 'electricPump'
Consider always using some project management tool. This way among other things, people can easily set up you project and help you out.

Java spring noob beans and configuration

I'm trying to run the fallowing classes.
package com.example.demo;
import org.apache.catalina.core.ApplicationContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
var factory = new AnnotationConfigApplicationContext(AppConfig.class);
test tst = factory.getBean(test.class);
tst.getDummy().test();
SpringApplication.run(DemoApplication.class, args);
}
}
App config class:
package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class AppConfig {
#Bean
public test gettest(){
return new test();
}
//
#Bean
public test2 gettest2(){
return new test2();
}
}
First test class:
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
#Component
public class test{
#Autowired
test2 dummy;
public void setDummy(test2 dummy) {
this.dummy = dummy;
}
public test2 getDummy() {
return dummy;
}
void test(){
System.out.println("test");
}
}
Second test class:
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
#Component
public class test2{
public test2(){
}
void test(){
System.out.println("test2");
}
}
I get this error at run time
Field dummy in com.example.demo.test required a single bean, but 2 were found:
- test2: defined in file [/Users/biliuta/IdeaProjects/demo/build/classes/java/main/com/example/demo/test2.class]
- gettest2: defined by method 'gettest2' in class path resource [com/example/demo/AppConfig.class]
If i comment out the public test2 gettest2() bean from AppConfig I'll get this error:
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'gettest': Unsatisfied dependency expressed through field 'dummy'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.test2' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
How come in the first case test2 bean is found and when I comment it out from AppConfig it is unable to find it anymore (in the first error message you can clearly see that test2 is found)? Is #Configure annotation mandatory to add beans to the context?
When you define #Component you define a bean which can be found for autowiring
When you define #Bean (in `#Configuration) you define a bean which can be found for autowiring
So you define twice same bean which caused spring to failed to know which one is the correct bean to autowire
Solution is to define only one time
how #Autowired works is it first try to find the required bean by type and a fallback mechanism is by bean name(ex: there are multiple beans for the same type)
but when you disable the #Bean annotation from AppConfig there should have been at least one bean of type Test2 as you have annotated Test2 with #Component annotation but it can't find it. To solve this you need to add #ComponentScan(basePackageClasses = { Test2.class }) on your AppConfig class as follows
#Configuration
#ComponentScan(basePackageClasses = { Test2.class })
public class AppConfig {
#Bean
public Test gettest(){
return new Test();
}
//#Bean
public Test2 gettest2(){
return new Test2();
}
}
but if you enable the bean annotation as follows
#Configuration
#ComponentScan(basePackageClasses = { Test2.class })
public class AppConfig {
#Bean
public Test gettest(){
return new Test();
}
#Bean
public Test2 gettest2(){
return new Test2();
}
}
you need to change the injection of Test2 on Test as by using
#Autowired
Test2 test2;
or by using
#Autowired
Test2 gettest2;
There are a few ways of making your class a bean in Spring / Spring Boot
Annotating your class with #Component or any other derived annotation(#Service, #Repository, #Controller, #RestController)
Defining your class as a bean in XML configuration
Using #Bean annotation(this one can be applied only to a method specify that it returns a bean to be managed by Spring context). #Bean annotation is usually declared in Configuration classes methods
When Spring initializes its context, it looks for any bean definitions and creates beans. In your case, it finds duplicate declarations of both test and test2, so you need either to remove your configuration class or remove the #Component annotations from your classes.
See Spring Bean documentation for more information

Spring Boot #Autowired object - Nullpointer Exception [duplicate]

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 3 years ago.
I am developing a spring boot application to send sms notification. This is my class for the purpose.
package org.otp.services;
import org.otp.Configurations;
import com.mashape.unirest.http.HttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
#Component
public class SmsService
{
private static final Logger LOG = LoggerFactory.getLogger(SmsService.class);
public String send(String mobile, String msg)
{
//Code
}
}
And this is the class which uses the above class for sending notification.
package org.otp.controllers;
import org.otp.Constants;
import org.otp.services.EmailService;
import org.otp.services.SmsService;
import org.otp.dto.MessageRequest;
import org.otp.dto.MessageResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
#Component
public class MessageController {
private static final Logger LOG = LoggerFactory.getLogger(MessageController.class);
#Autowired
SmsService smsService;
public void sendMessageToAlert(#RequestBody MessageRequest messageRequest)
{
String smsStatus = "FAIL";
MessageResponse messageResponse = new MessageResponse();
//1. Nullpointer
smsStatus = smsService.send(messageRequest.getMobileNo(),messageRequest.getMessage());
}
}
Main Class
package org.otp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
#SpringBootApplication
#EnableAsync
public class OtpServiceApplication implements ApplicationRunner
{
public static void main(String[] args) {
SpringApplication.run(OtpServiceApplication.class, args);
}
}
Problem is, I get a nullpointer exception in the (1) stating that my SmsService object is null. And my main class is in package org.otp so the two classes here falls under sub package so no need of component scan.
Therefore I am confused what to do to solve this. I have tried many answers here like adding a #Component annotation and #ComponentScan in main class but nothing works. Could someone please point out my mistake here.
Thanks in advance.
If your #Autowired annotation is not working and throws NPE ,it means that spring fails to create an instance of the component class in the application context . Try to:
Verify that the classes are in class path for scanning and also check to ensure that all auto-wired classes have the annotation #Component to enable them to be picked up during class path scanning.
Check the spring boot start up logs to verify if there are any errors
during bean creation.
Check to ensure all related classes used in the service layer are auto-wired properly and that the injected classes are annotated with #Component .
For further help please share the main application class along with your project structure.
Since you are using springboot , it is preferable to use the sprinboot stereotype annotations instead of the #Component annotation, if you are building a standard springboot web application.
#Service : for the service layer.
#Controller : for the controller layer . Also,DispatcherServlet will look for #RequestMapping on classes which are annotated using #Controller but not with #Component.
In Springboot application's main class add following annotation
#SpringBootApplication
#ComponentScan(
basePackages = {"org.otp.*"}
)
public class YourSpringMainClass{
public static void main(String[] args) {
SpringApplication.run(YourSpringMainClass.class, args);
}
}
While using annotations we should configured with #ComponentScan annotation to tell Spring the packages to scan for annotated components. This should be used in mail class(Which class wants to load first) in your case you are working with spring boot so you should use this annotation in Springboot application's main class. Like below
#SpringBootApplication
#ComponentScan(
basePackages = {"org.otp.*"}
)
public class YourSpringMainClass{
public static void main(String[] args) {
SpringApplication.run(YourSpringMainClass.class, args);
}
}

No qualifying bean of type 'concert.PerformanceImp' available

I am still a beginner in Spring Framework so I tried to code a program about "introduction" in Spring AOP but I am facing an error while compiling. Please find below the classes in the package concert:
PerformanceImp.java
package concert;
import org.springframework.stereotype.Component;
#Component
public class PerformanceImp implements Performance {
public void perform() {
System.out.println("This is the performance function");
}
}
Performance.java
package concert;
public interface Performance {
public void perform();
}
Encoreable.java
package concert;
public interface Encoreable {
void performEncore();
}
DefaultEncoreable.java
package concert;
import org.springframework.stereotype.Component;
#Component
public class DefaultEncoreable implements Encoreable {
public void performEncore() {
System.out.println("This is the performEncore function");
}
}
EncoreableIntroducer.java
package concert;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;
#Component
#Aspect
public class EncoreableIntroducer {
#DeclareParents(value="concert.Performance+",
defaultImpl=DefaultEncoreable.class)
public static Encoreable encoreable;
}
ConcertConfig.java
package concert;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
#Configuration
#EnableAspectJAutoProxy
#ComponentScan("concert")
public class ConcertConfig {
}
And the main class:
Main.java
package concert;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(ConcertConfig.class);
PerformanceImp pi = (PerformanceImp) context.getBean(PerformanceImp.class);
((Encoreable) pi).performEncore();
pi.perform();
}
}
I am getting the error:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'concert.PerformanceImp' available
Any help please ?
You cannot access the implementation (PerformanceImp) by default, because you enabled AOP, which sets to target interfaces instead of implementation. If you would remove EnableAspectJAutoProxy, you would see the code would work fine.
To understand a bit more about how AOP targeting works, take a look at this Spring Documentation
Spring AOP can also use CGLIB proxies. This is necessary to proxy
classes rather than interfaces. CGLIB is used by default if a business
object does not implement an interface. As it is good practice to
program to interfaces rather than classes; business classes normally
will implement one or more business interfaces. It is possible to
force the use of CGLIB, in those (hopefully rare) cases where you need
to advise a method that is not declared on an interface, or where you
need to pass a proxied object to a method as a concrete type.
So you have two options:
Take the interface when trying to get the bean from the ApplicationContext.
Enable AOP to target concrete classes instead.
To do this point #2, modify your annotation as follows:
#EnableAspectJAutoProxy(proxyTargetClass = true)
Try:
Performance pi = context.getBean("performanceImp", Performance.class);
instead of:
PerformanceImp pi = (PerformanceImp) context.getBean(PerformanceImp.class);

Javaconfig bean overriding failing with List injected

I consider injection of beans as a List of automatically detected beans: I introduce several beans implementing the same interface and inject all of them as a List in a later bean.
I've not been able to find official documentation related to this feature. My single source is http://www.coderanch.com/t/605509/Spring/Java-config-autowired-List
Considering this feature, I have an issue with Bean overring: I would like to override a bean defined throught a no-arg method with a bean defined with the List of detected beans. However, spring behave like the second bean definition does not exist.
It can be reproduced with the following test:
import java.util.Date;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
public class SpringTest {
#Test
public void shouldtestSpringDifferentMethodNames() {
AnnotationConfigApplicationContext ctx2 = new AnnotationConfigApplicationContext(AConfig.class, CConfig.class);
Assert.assertEquals("overriden", ctx2.getBean("bean"));
}
#Configuration
public static class AConfig {
#Bean
public Object bean() {
return "not overriden";
}
}
#Configuration
public static class CConfig extends AConfig {
#Bean
public Date anotherBean() {
return new Date();
}
#Bean
public Object bean(List<? extends Date> someDate) {
return "overriden";
}
}
}
If this is an expected behavior, how can I achieve such an overriding?
documentation for list autowire can be found at spring documentation
overriding of beans by id or name is not official spring feature - look for that question for more details
This has been considered as a bug by the Spring team: https://jira.springsource.org/browse/SPR-10988
A recent piece of documentation can be found at: http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-autowired-annotation (Thanks Alexander Kudrevatykh for the 2.5 source)

Categories