Class instantiation using the Autowired annotation - java

Is its advisable to instantiate the class using #Autowired annotation like below.
#Autowired
public static Car = new Car();

Case 1
If you are trying to autowire an attribute like following:
#Autowired
public Car car;
then Spring will try to search for a Bean definition in Spring context and will also instantiate it, hence no need to again invoke constructor.
Case 2
If you are getting confused with constructor autowire like following:
#Autowired
public Driver(License license){
this.license = license;
}
Here, it is trying to get the Bean of "License" class autowired, and it is not autowireing Driver.
In your case, I feel it is case 1.
If you are trying to set it manually cause you are seeing it as not initialized, then check the spring application context configuration file/class. You will need to have something like following in it:
<context:component-scan base-package="com.test.packagename" />
If using AppConfig class then:
#Configuration
#ComponentScan("com.test.packagename")
public class AppConfig {
}
Also, make sure that your spring core is deployed in lib where it is executing.
Also check that you are instantiating the class by using Spring application context as follows:
AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Car car= (Application)context.getBean("car");
Try to refer this: http://websystique.com/spring/spring-dependency-injection-annotation-beans-auto-wiring-using-autowired-qualifier-resource-annotations-configuration/
Happy coding DBZ fan :-)

Related

How to autowire a bean into a 2 different controllers (Spring)

I am learning spring and i have a problem that i do not know how to solve.
#Service
#Transactional
public class SchoolService {
#Autowired
private CourseDao courseDao;
#Autowired
private EducationDao educationDao;
#Autowired
private StudentDao studentDao;
#Autowired
private TeacherDao teacherDao;
#Autowired
private StatisticsDao statisticsDao;
............
}
This code is injecting my DAOS into this service class but then i need to inject the class above into two controllers.
One way i have tried was with this code but that did not work.
#Autowired
SchoolService sm;
How would i inject it into my controller class. I have tried making the controller class a #Component but nothing seems to work.
ClassPathXmlApplicationContext container = new ClassPathXmlApplicationContext("application.xml");
SchoolService sm = container.getBean(SchoolService.class);
This way works but i do not want to create a new applicationcontext for each time i want to get that bean.
Yes i am using xml at the moment, please don't shoot me :D
Thanks.
Try creating the controller bean in the application.xml file instead of annotating the controller.
Since its obviously an educational question, I'll try to provide a very detailed answer as much as I can:
Once basic thing about spring that all the auto-wiring magic happens only with beans that are managed by spring.
So:
Your controllers must be managed by spring
Your service must be managed by spring
Your DAOs must be managed by spring
Otherwise, autowiring won't work, I can't stress it more.
Now, Think about the Application Context as about the one global registry of all the beans. By default the beans are singletons (singleton scope in terms of spring) which means that there is only one object (instance) of that bean "retained" in the Application Context.
The act of autowiring means basically that the bean (managed by spring) - controller in your case has dependencies that spring can inject by looking in that global registry, getting the matching bean and setting to the data field on which the #Autowired annotation is called.
So, if you have two controllers (again, both managed by spring), you can:
#Controller
public class ControllerA {
#Autowired
private SchoolService sm;
}
#Controller
public class ControllerB {
#Autowired
private SchoolService sm;
}
In this case, the same instance of school service will be injected into two different controllers, so you should good to go.

How to create a Spring Bean using existing library

I'm new to Spring and am using an existing Spring library/api. All beans are configured in java classes, ie. no xml, and the existing configuration comes with one line in the main method:
SpringApplication.run(ServerExchange.class, args);
The library deals with the protocols to interface with a private server, I've been able to create normal instances of classes, ie:
AccountManager aM = new AccountManager()
however the configuration that's meant to be autowired into each class, such as the AccountManager, isn't being done as it's intended to be created as a "bean", so when I go to use the AccountManager, it's dependencies that are #Autowired are null
I've been looking online and trying to find an example of how to go from the first given line in the main method however what I can find online is mainly based around either xml or an "ApplicationContext". I'm not sure how to take the first step and simply create a bean, can anyone please provide an example of the code to create an AccountManager bean?
Thanks in advance.
Edit:
To clarify, I'm interested in the code required in the main method of how to get the instance of it once the beans have been set up in their respective classes.
If you want to configure been at class, you can do it as follow.
#Configuration
public class AppConfig {
#Bean
public AccountManager accountManager() {
return new AccountManager();
}
}
Or If you wanna use xml then
<beans>
<bean id = "accountManager" class = "packageName.AccountManager" />
</beans>
Then you can use it in a class as follows.
#Autowired
AccountManager accountManager ;
To create a bean of AccountManager do following:
#Bean
public AccountManager accountManager() {
return new AccountManager();
}
If you need any field to be autowired in an object you cannot instantiate it with new because when you do so Spring don't know about it.
You can do the following :
class MyClass{
#Autowired
ApplicationContext applicationContext;
public void method(){
AccountManager ac = applicationContext.getBean(AccountManager.class);
}
}
if your AccountManager is known by Spring. With an annotation on the class like #Component
As I'm not a user of Spring-boot in this way I found here : How to get bean using application context in spring boot how to get ApplicationContext in a different way than the one I'm using

Using class.forname but want to autowire members of the target class

I have this requirement,
My framework is in a way that it reads the class name from the configuration file as a string and I would like to use methods inside that class.
Obvious solution is to use reflection,
I have used reflection and able to call methods I wanted, but the problem is the variables inside the target class are not autowired. I understand I am not letting spring to autowire the fields by using reflection (Spring with class.forname()).
Is there a way for me to autowire the class variables instead of creating new instance? Or Am I in a deadlock situation?
Option 1: If you have access to the current Spring ApplicationContext, you could do this as follows:
String className = <load class name from configuration>
Class<?> clazz = Class.forName(className);
ApplicationContext applicationContext = <obtain Spring ApplicationContext>
applicationContext.getBean(clazz);
This of course means that the class whose instance you wish to load is a Spring managed bean. Here is a concrete example:
package org.example.beans;
#Component
class Foo { ... }
#Component
class SpringApplicationContext implements ApplicationContextAware {
private static ApplicationContext CONTEXT;
#Override
public void setApplicationContext(final ApplicationContext context) throws BeansException
CONTEXT = context;
}
public static <T> T getBean(String className) {
return CONTEXT.getBean(Class.forName(className));
}
}
Option 2: You could manually create an instance of the required class and then ask Spring to populate its dependencies.
This again requires access to the ApplicationContext. For example:
T object = Class.forName(className).newInstance();
applicationContext..getAutowireCapableBeanFactory().autowireBean(object);
It's possible. Have a look at how Spring's JUnit test integration does it. That's in the spring-test module.
The runner is SpringJUnit4ClassRunner, but the actual injection code is in DependencyInjectionTestExecutionListener.injectDependencies. It uses a Spring context that implements AutowriteCapableBeanFactory.
The code to do this looks like below. Note that this assumes that you have used annotations to indicate which fields need to be autowired.
Object bean = ...;
AutowireCapableBeanFactory beanFactory = ...;
beanFactory.autowireBeanProperties(bean, AutowireCapableBeanFactory.AUTOWIRE_NO, false);
beanFactory.initializeBean(bean, "beanName");

Autowiring working in one class but not in other

I have an autowired class like this
#Component
public class APIPermissionCheck {
..............
}
its injecting fine in one java file. But its always returning null in other java file. What could be the possible cause of this? How to debug/fix this issue?
working fine in this class
#Repository("MyClassRepo")
public class MyClassRepoImpl implements MyClassRepo {
.......
#Autowired
private APIPermissionCheck apiPermissionCheck;
.......
}
Not working in this class
public class ApiConnection {
.......
#Autowired
private APIPermissionCheck apiPermissionCheck;
.......
}
The class ApiConnection is not found by spring because it is neither annotated as #Component neither as #Repository.
If you annotate your class with #Component it should work.
Also ensure that the package with the class is scanned by spring.
Does your second class marked as spring bean?
Do you scan the package in which your second class by spring?
you can view configuration sample at spring site
EDIT :
Create a setter for the bean you're trying to inject
public void setApiPermissionCheck(APIPermissionCheck apiPermissionCheck){
this.apiPermissionCheck = apiPermissionCheck
}
Try to add an interface to ApiConnection to verify it's being loaded by Spring Container.
ApiConneection implements ApplicationContextAware {
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
logger.info("Initializing context is:" + applicationContext);
}
....
}
do the same for the Autowiring classes and verify they are being loaded withint the same context.
You problem is probably:
The bean is not initialized with a spring
Autowired beans belongs to another context
Context for ApiConnection is not instructed with <context:annotation-config/>
I found the solution. As ApiConnection object is being created a lot of places manually so spring framework is not autowiring it.
I met the same problem and solved it by adding a #Service to the second class public class ApiConnection. The first class already has a #Service. In this step, it still does not work (return NullPointerException). In addition, in the Class that use ApiConnection, let's say ApplicationImpl, I add #Autowired on ApiConnection apiConnection; (ApiConnection apiConnection = new XXX was used before). Then it works.

How to inject dependencies into a self-instantiated object in Spring?

Let's say we have a class:
public class MyClass {
#Autowired private AnotherBean anotherBean;
}
Then we created an object of this class (or some other framework have created the instance of this class).
MyClass obj = new MyClass();
Is it possible to still inject the dependencies? Something like:
applicationContext.injectDependencies(obj);
(I think Google Guice has something like this)
You can do this using the autowireBean() method of AutowireCapableBeanFactory. You pass it an arbitrary object, and Spring will treat it like something it created itself, and will apply the various autowiring bits and pieces.
To get hold of the AutowireCapableBeanFactory, just autowire that:
private #Autowired AutowireCapableBeanFactory beanFactory;
public void doStuff() {
MyBean obj = new MyBean();
beanFactory.autowireBean(obj);
// obj will now have its dependencies autowired.
}
You can also mark your MyClass with #Configurable annotation:
#Configurable
public class MyClass {
#Autowired private AnotherClass instance
}
Then at creation time it will automatically inject its dependencies. You also should have <context:spring-configured/> in your application context xml.
Just got the same need and in my case it was already the logic inside non Spring manageable java class which had access to ApplicationContext. Inspired by scaffman.
Solved by:
AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory();
factory.autowireBean(manuallyCreatedInstance);
I used a different approach. I had spring loaded beans that I wanted to call from my extended classes of a third-party library that created its own threads.
I used approach I found here https://confluence.jaytaala.com/display/TKB/Super+simple+approach+to+accessing+Spring+beans+from+non-Spring+managed+classes+and+POJOs
In the non-managed class:
{
[...]
SomeBean bc = (SomeBean) SpringContext.getBean(SomeBean.class);
[...]
bc.someMethod(...)
}
And then as a helper class in the main application:
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
#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;
}
}
I wanted to share my solution that follows the #Configurable approach as briefly mentioned in #glaz666 answer because
The answer by #skaffman is nearly 10 years old, and that does not mean not good enough or does not work
The answer by #glaz666 is brief and didn't really help me solve my problem but, did point me in the right direction
My setup
Spring Boot 2.0.3 with Spring Neo4j & Aop starts (which is irrelevant anyway)
Instantiate a bean when Spring Boot is ready using #Configurable approach (using ApplicationRunner)
Gradle & Eclipse
Steps
I needed to follow the steps below in order to get it working
The #Configurable(preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false) to be placed on top of your Bean that is to be manually instantiated. In my case the Bean that is to be manually instantiated have #Autowired services hence, the props to above annotation.
Annotate the Spring Boot's main XXXApplicaiton.java (or the file that is annotated with #SpringBootApplication) with the #EnableSpringConfigured and #EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
Add the dependencies in your build file (i.e. build.gradle or pom.xml depending on which one you use) compile('org.springframework.boot:spring-boot-starter-aop') and compile('org.springframework:spring-aspects:5.0.7.RELEASE')
New+up your Bean that is annotated with #Configurable anywhere and its dependencies should be autowired.
*In regards to point #3 above, I am aware that the org.springframework.boot:spring-boot-starter-aop transitively pulls the spring-aop (as shown here mavencentral) but, in my case the Eclipse failed to resolve the #EnableSpringConfigured annotations hence, why I explicitly added the spring-aop dependency in addition to the starter. Should you face the same issue, just declare the dependency or go on adventure of figuring out
Is there a version conflict
Why the org.springframework.context.annotation.aspect.* is not available
Is your IDE setup properly
Etc etc.
This worked for me:
#Configuration
public class AppConfig {
#Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}
See more information: https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html
Found the following way useful for my use case. Sharing here for reference, credit goes to the blogger entirely. This creates a static field and populates that from Spring and then provides a public static method which returns the field populated above.
https://sultanov.dev/blog/access-spring-beans-from-unmanaged-objects/

Categories

Resources