I have a class that is annotated #Component that was then #Autowired into another class. However, I need to remove this #Component annotation and instead, create it with an #Bean annotated method in the class where its was previously autowired.
Where previously the classes looked like:
#Component
public class MyClass implements IMyClass
{
// Stuff
}
#Configuration
public class MyUsingClass
{
#Autowired
private IMyClass myClass;
private void methodUsingMyClass()
{
myClass.doStuff();
}
}
So now I have removed the #Component annotation and written a #Bean annotated method like this:
public class MyClass implements IMyClass
{
// Stuff
}
#Configuration
public class MyUsingClass
{
#Bean
public IMyClass getMyClass()
{
return new MyClass();
}
....
}
My question is around replacing the previous call of myClass.doStuff() to use the new bean. Do I now pass in a parameter of type MyClass to the private method:
private void methodUsingMyClass(final MyClass myClass)
{
myClass.doStuff();
}
... or do I call this method directly (doesn't seem the correct way to me):
private void methodUsingMyClass()
{
getMyClass().doStuff();
}
... or are neither of these correct?
I think you misunderstand the #Bean annotation. It can be used to create a Bean. So basically spring will scan all classes, will find your #Bean and create a Bean, not more. You can now use this bean, like if you would use one created with <bean></bean>. To actually use the bean you need to either get it from ApplicationContext or #Autowire it. Of course you can still use that function like any other function in your code, to create a new instance of that object, but that would contradict to what you want to achieve with beans
Using Annotations that solutions
public class MyClass implements IMyClass{
private OtherClassInjection otherClassInjection;
private OtherClassInjection2 otherClassInjection2;
MyClass(OtherClassInjection otherClassInjection, OtherClassInjection2 otherClassInjection2){
this.otherClassInjection=otherClassInjection;
this.otherClassInjection2=otherClassInjection2;
}
public void useObject(){
otherClassInjection.user();
}
}
#Bean(name = "myClass")
#Autowired
#Scope("prototype") //Define scope as needed
public MyClass getMyClass(#Qualifier("otherClassInjection") OtherClassInjection otherClassInjection,
OtherClassInjection2 otherClassInjection2) throws Exception
{
return new MyClass(otherClassInjection, otherClassInjection2);
}
that logical, it's work injection #Autowired when create a Bean if context are know that bean, that you will to want inject.
I'm use that way.
Related
I have a requirement where I want to call a parameterised constructor of a class annotated with #Component inside another class which is annotated with #Service
feel free if you didn't get my question.
#Service
Class ServiceClass{
//here I want to create ComponentClass instance by Spring.
Result result=new ComponentClass(sending data to get result);
}
#Component
Class ComponentClass {
Component(received data){
}
}
I think you should try "Autowired" keyword. It says "Hey Spring Framework try to initialize the variable for me".
#Autowired
Result result=new ComponentClass(sending data to get result);
Whenever you define a #Servive or a #Component a bean of that type will be created (keep in mind that all beans are singletons).
A bean can be injected into any other spring managed bean by making use of this annotation:
#Service
Class ServiceClass{
#Autowired
Result result;
}
Using beans (components, services etc.) is not always needed and especially in the case, you need an non-singleton class, things can get tricky because of two reasons:
You won't be able to use annotations on that class
A non-annotated (spring managed bean) class do not support injection.
To inject a bean inside a class that is not annotated you will need to define a spring context:
#Component
public class SpringContext implements ApplicationContextAware {
private static ApplicationContext context
public static <T extends Object> T getBean(Class<T> beanClass) {
return context.getBean(beanClass);
}
#Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
SpringContext.context = context;
}
}
and then into any class:
Class ServiceClass{
Result result = SpringContext.getBean(Result.class);
}
where result is a either component or service.
I'm new to spring boot, and I need to know how to use #autowired in an attribute that needs parameters to be instantiated.
Please bear in mind the following illustrative situation. It would be something like this:
public class MyClassA{
public SpecificClass myMethod(){
//some logic
}
}
public class MyClassB extends MyClassA{
#Autowired
MyComponent myComponent (myMethod()); //here is my doubt, because my component needs a parameter to be built
}
#Component
public class MyComponent{
public MyComponent(SpecificClass foo){
this.foo=foo;
}
That's not really proper design if your intention is to work with dependency injection. There shouldn't be a direct dependency to the superclass' method like that. Injecting the dependencies indirectly as you're supposed to do would result in something like the following
public class MyClassB extends MyClassA {
#Autowired
private MyComponent myComponent;
}
#Configuration
public class SomeConfig {
#Bean
#Autowired
public MyComponent createComponent(SpecificClass foo) {
// SpecificClass is also injected, providing another layer of indirection
return new MyComponent(foo);
}
}
#Autowired only tells Spring to inject a component into a constructor, field, or method parameter. The injected component is instantiated by the bean container before that. I assume what you are looking for is a way to create MyComponent in such a way that it also receives a Spring Bean.
In your example you could achieve this with the following
#Configuration
public class MyClassA{
#Bean //the bean would have the name 'myMethod', so maybe change that
public SpecificClass myMethod(){
//some logic
}
}
//this needs to be a component, service, ...
#Component
public class MyClassB {
#Autowired
MyComponent myComponent;
}
#Component
public class MyComponent{
#Autowired //Spring wires the Bean 'myMethod' in here, autowired is not needed in the latest Spring Versions
public MyComponent(SpecificClass foo){
this.foo=foo;
}
}
This is a basic Spring question, and not specific to Spring Boot. To better understand wiring you can take a look at the Spring 4 Framework Reference Documentation.
I have two methods annotated with #Bean. I am calling one #Bean annotated method from another. Does it mean it creates two beans of the same type?
Here's my code:
#Configuration
#Import({BaseConfig.class})
public class TestConfig{
#Autowired
BaseConfig baseconfig;
#Bean
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public SampleTestClass sampleTest() {
return new SampleTestClass(baseconfig.createNewBean());
}
}
#Configuration
#Import(SomeClassConfig.class)
public class BaseConfig {
#Autowired
private int someAttribute;
#Bean
public SampleTest createNewBean() {
return new SampleTest(someAttribute);
}
}
No, it wouldn't.
SampleTest has a singleton scope which is the default, so even if you call the method "directly", Spring will make sure that there is only one instance per container.
No, it doesn't. Spring automatically proxies #Configuration classes at runtime and decorates #Bean methods to provide the correct scope behavior.
However, in your case it would be cleaner not to tangle the two configurations unnecessarily. Instead, you could do this:
#Bean
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public SampleTestClass sampleTest(SampleTest dependency) {
return new SampleTestClass(dependency);
}
I have to create a instance of a class, that have autowired elements, for test.
public class MyClass extends SomeOtherClass {
#Autowired
public MyClass(OtherClass1 one, OtherClass2 two){
super(one, two)
}
}
How can i in code create instance of this class, with the arguments wired in though spring?
Your test can be made Spring-aware if you use the SpringJUnit4ClassRunner to read in your Spring Context to be used in the test. For instance:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"the-config.xml"})
public final class MyClassTests {
#Autowired
private MyClass testee;
#Test
public void testSomething() {
assertThat(testee).doesSomethingExpected();
}
}
Note that you should reuse as much of your production config as possible and not create a parallel Spring Context config that mirrors it.
Instead of passing the other elements in as constructor arguments, you Autowire them as properties. Spring will then inject the objects.
public class MyClass extends SomeOtherClass {
#Autowired
private OtherClass1 one;
#Autowired
private OtherClass2 two
public MyClass(){
super(one, two)
}
}
Edit: Based on http://www.mkyong.com/spring/spring-auto-wiring-beans-with-autowired-annotation/, adding #Autowired to the constructor is also valid.
If you want to Autowire MyClass, you must annotate it with #Component or a similar annotation such as #Service.
#Component
public class MyClass extends SomeOtherClass
Then, you can use it in other classes
public class ClassThatUsesMyClass {
#Autowire
private MyClass myClass;
}
I have a factory class and I wonder if it is possible to inject the AnimalMapper factory class into other beans that needs it?
AnimalMapper factory class
public static Mapper create(final String type) {
if (type.equalsIgnoreCase("dog")) {
return new DogMapper();
} else if (type.equalsIgnoreCase("cat")) {
return new CatMapper();
} ...
}
Currently I am using AnimalMapper.create(...)
Here is sample code
public class TestClass{
//member variable defination.
#Inject
AnimalMapper animalMapper; //defining mapper instance
}
I am not sure if you are looking for this but if you can clarify question more then can add more details.
What do you want to achieve? Something like this with CDI:
public class TestClass{
#Inject #Any
Instance<Mapper> mapper;
public void myMethod(){
if(isCat()){
mapper.select(new AnnotationLiteral<Cat>(){}).get();
}
if(isDog()){
mapper.select(new AnnotationLiteral<Dog>(){}).get();
}
}
}
#Dog
public class DogMapper implements Mapper...
#Cat
public class CatMapper implements Mapper...
See the reference documentation: http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/pdf/spring-framework-reference.pdf
Pages 43-43 on factory-method in your bean definition.