I have a Spring Service class and I want to put a static variable in it that will be initialized with values once when the Service is created by Spring by Autowired.
I want to achieve something like this:
#Service
public class MyServiceImpl implements IService {
public static HashMap<String,String> settings = new HashMap<String,String>();
public MyServiceImpl() {
settings.put("key1","value1");
settings.put("key2","value2");
}
And then when I Autowired that Service the variable will be initialized just once.
Is there any solution how to achieve that?
You can use #PostConstruct:
#PostConstruct
private void init() {
//fill values into map here
}
Spring Beans' default scope is singleton, so you can use constructor and #PostConstruct as well as InitializingBean interfaces or static initializer.
Some suggestion: dont use static variable if not necessary, it is not a good practice, easy to create memory leak etc. If you try to get the map before spring container initialize the bean, it will be empty and other problems can occure.
Related
I'd like to know what are the differences between the two examples below. One is using #PostConstruct init method to ensure autowired bean is initialized, and the other one is using constructor with #Autowired to ensure any needed beans are initialized.
I am curious
If there is any functional differences
If one is better than the other, why? (Maybe initialization speed, less call stack, less memory usage, etc.)
Thanks in advance :)
#Component
public class MyBean {
#Autowired
public MyBean(SomeOtherBean someOtherBean) {
...
}
...
}
#Component
public class MyBean {
#Autowired
private SomeOtherBean someOtherBean;
#PostConstruct
public void init() {
...
}
...
}
in the first case, if I'm going to use MyBean.class without in a none Spring framework project I'll need to pass SomeOtherBean so I know the object is created correctly. but in the second case, I would have done new MyBean() and then after I'll get NullPointerException when using it because the object depends on SomeOtherBean.
so the first one is much cleaner.
Autowired constructor will not create the instance unless it has someotherbean available, that means it fast fails and will not even try to create the instance before someotherbean is available. If you do not have an autowired constructor it will create the instance and the bean is available in container, then inject the someotherbean when it is available. Whatever inside the #PostConstruct annotated method will execute after the instance is created. Please read the following will get better idea
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#spring-core
I have a createEntity method that is static, because i need to call it from other entities, inside this method, i need to call a repository, but logically i can't do it because it's non static.
public static Client createEntity(EntityManager em) {
default_operation = operationRepository.save(OperationResource.createEntity(em));
}
I wouldn't ask if i hadn't my head blown away by this, i tried to use #Autowired constructors as other solution suggested but this won't work for a repository.
If anyone has an idea, or a workaround, i would appreciate it!
Using static methods causes problems (not only in Spring). One of the reasons is that the autowired properties of a class are not available in a static context. They are only injected during certain stages of Spring's lifecycle.
You should declare the class that contains the createEntity method as a Spring bean (for example with #Component). Then you can inject this bean (with #Autowired) in all other classes that need to call createEntity.
I DO NOT recommend this, but because of any reason if you can't change the original class (to a singleton), you can consider the below approach which calls the createEntity(entityManager) inside #PostConstruct method:
public class MyRepository {
private EntityManager entityManager;
private static Client client;
#Autowired
public MyRepository(EntityManager entityManager) {
this.entityManager = entityManager;
}
#PostConstruct
public void init() {
//Now call your createEntity(entityManager) method
client = EntityUtils.createEntity(entityManager);
}
}
Following this code:
#Component
public class ClassC extends ClassA<T> implements ClassB {
private String preferredDateTimeFormat = null;
My process is using this class after calling a request from client.
Per each request I want to keep the preferredDateTimeFormat value, what is actually being made that, the preferredDateTimeFormat variable is being used for all of my requests.
What can I do to solve it?
Use #Scope on your class with value = request
like this
#Component
#Scope(value="request", proxyMode =ScopedProxyMode.TARGET_CLASS)
public class ClassC extends ClassA<T> implements ClassB {
private String preferredDateTimeFormat = null;
You can find more information on Spring Bean Scopes here
There are multiple ways.
You can define a Request Scope bean and place the preferredDateTimeFormat there.
OR
You can define ThreadLocal property and place the value there.
I'm not entirely sure if you mean you want a ClassC instance per request or a new instance everytime it is used but you might want to look into the #Scope annotation with its values Prototype and Request.
See Spring Bean Scopes.
What is the difference between anotate #Autowired to a property or do it in the setter?
As far as I know they both have the same result, but is there any reason to use one over the other?
UPDATE (to be more concise)
Is there a difference between this
package com.tutorialspoint;
import org.springframework.beans.factory.annotation.Autowired;
public class TextEditor {
private SpellChecker spellChecker;
#Autowired
public void setSpellChecker( SpellChecker spellChecker ){
this.spellChecker = spellChecker;
}
public void spellCheck() {
spellChecker.checkSpelling();
}
}
and this
package com.tutorialspoint;
import org.springframework.beans.factory.annotation.Autowired;
public class TextEditor {
#Autowired
private SpellChecker spellChecker;
public TextEditor() {
System.out.println("Inside TextEditor constructor." );
}
public void spellCheck(){
spellChecker.checkSpelling();
}
}
Sometimes you need an instance of class A, but you do not store A in the fields of the class.
You just need A instance to perform a one-shot operation. Or, you use A instance to obtain an instance of B, and you are storing B in the field.
In those cases, a setter (or constructor) autowire will suit you better.
You will not have unused class-level fields.
Concrete example:
You need to construct RabbitTemplate (an object that sends messages to RabbitMQ)
To construct it, you need ConnectionFactory
http://docs.spring.io/spring-amqp/docs/latest_ga/api/org/springframework/amqp/rabbit/core/RabbitTemplate.html#RabbitTemplate-org.springframework.amqp.rabbit.connection.ConnectionFactory-
You do not need to store that ConnectionFactory. In that case, code that looks like this:
Class MyClass {
private RabbitTemplate template;
#Autowired
void setConnectionFactory(ConnectionFactory c) {
template=new RabbitTemplate(c);
}
}
...will serve you better than directly autowiring the ConnectionFactory field.
In this example, autowiring at the constructor level would be even better, because your object will always be completely constructed. It will be clear that ConnectionFactory is a mandatory dependency, not an optional one.
With #Autowired annotation, you don't need a setter method. Once your bean's constructor is done with allocating/creating the object, Spring will scan for this annotation and would inject the object instances that you annotated.
While if you have setter and if you are still using xml config, you would explicitly set properties.
Having said that, You could annotate your constructor and setter method with autowired annotation which i would prefer as this would give me flexibility later on to move away from Spring (although i wont do it).
If you use #Autowired annotation on a property, spring will initiate the property using spring.xml. You don't need setter in this case.
If you use #Autowired annotation on a setter, you are specifying to spring that it should initiate this property using this setter method where you can add your custom code, like initializing some other property with this property.
Usage with Example:
In the case of using DAO operations using JdbcTemplate, you need DataSource as an input to JdbcTemplate, but DataSource is not required as a property in itself. So you can use DataSource Setter to initialize JdbcTempate by auto-wiring DataSource Setter. Please see the below code:
class DaoDemo{
//#Autowired
//private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
#Autowired
public void setDataSource(DataSource dataSource){
//this.dataSource = dataSource;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public int getTableRowCount(){
String sql = "SELECT COUNT(*) FROM DEMOTABLE";
//jdbcTemplate.setDataSource(dataSource); //No need to do this as its done in DataSource Setter now.
return jdbcTemplate.queryForObject(sql,Integer.class);
}
In the above code, the only use of dataSource was to get passed in JdbcTemplate. So, creating a property of dataSource doesn't make sense here. So, just use the #Autowired on setter method of DataSource bean to get its entry from spring.xml and make use of it at that particular time itself.
There are 3 types of autowiring:
Property based
#Autowired
private MyService service;
Constructor based. Note in Spring Boot you don't even need #Autowired annotation in this case:
class MyController {
private final MyService service;
public MyController(MyService service) {
this.service = service;
}
}
Setter based:
private MyService service;
#Autowired
public void setService(MyService service) {
this.service = service;
}
It is recommended to use Constructor based, then if not possible, Setter based and lastly Property based.
Why?
First, because in Constructor based you don't even use any Spring annotations. This helps you transition to different frameworks.
Second, Constructor or Setter based, make unit testing much easier. You don't need to use any Spring specific testing tools and you can only use Junit and Mockito.
Third, Constructor based is good because you can declare the property as final and not expose setters which helps with immutability and thread safety of the class.
Autowiring works best when it is used consistently across a project. If autowiring is not used in general, it might be confusing to developers to use it to wire only one or two bean definitions. With #Autowired on a field you don't need a setter method, which, on one hand makes the class smaller and easier to read, but on the other hand makes mocking the class a bit uglier.
Explicit dependencies in property and constructor-arg settings always override autowiring. You cannot autowire so-called simple properties such as primitives, Strings, and Classes (and arrays of such simple properties). This limitation is by-design.
Autowiring is less exact than explicit wiring. Spring is careful to avoid guessing in case of ambiguity that might have unexpected results, the relationships between your Spring-managed objects are no longer documented explicitly.
Wiring information may not be available to tools that may generate documentation from a Spring container.
Multiple bean definitions within the container may match the type specified by the setter method or constructor argument to be autowired. For arrays, collections, or Maps, this is not necessarily a problem. However for dependencies that expect a single value, this ambiguity is not arbitrarily resolved. If no unique bean definition is available, an exception is thrown.
If you can, you should avoid the setter. If you don't need it, it's better when it doesn't exists, right?
I personally prefer Guice allowing me to write
public class TextEditor {
private final SpellChecker spellChecker;
#Inject public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
public void spellCheck(){
spellChecker.checkSpelling();
}
}
This goes a step further: With a final field, I know it won't ever change and I get the multithreading visibility guarantee.
There is one case where using #Autowired on an OPTIONAL property would not work.
If you want to do some initialization using that property, it might not be set before the constructor is called, and since it is optional, you cannot put it as an argument in the constructor.
In that case it is better to use an #Autowired setter method, so you can perform the initialization once the property is autowired.
I have a problem with injecting a bean into a helper class. It works basically like this: I create an object in the page constructor that does some work, returns some data and I show these on the page. In this helper object, a service should be injected via #Autowired annotation. However, I always get a null pointer exception when I use it. I also tried #SpringBean but it didn't help. On the other hand, when I inject this service directly into the page with #SpringBean, it's accessible and works fine. Do you know where the problem is?
This is the page:
public class Page extends BasePage {
public Page() {
HelperObject object = new HelperObject(new Application("APP_NAME"));
String result = object.getData();
add(new Label("label", result));
}
}
Helper object:
public class HelperObject {
private Application app;
#Autowired
private Service service;
public HelperObject(Application app) {
this.app = app;
}
public String getData() {
// use service, manipulate data, return a string
}
}
You can inject dependencies into non-Spring-non-Wicket-new-created objects using #SpringBean by calling InjectorHolder.getInjector().inject(this); in its constructor.
For example:
class MyPojo {
#SpringBean
MyDumbDAO dao;
MyPojo() {
InjectorHolder.getInjector().inject(this);
}
void justDoIt() {
dao.duh(); // dao is there!
}
}
Note that it will only work if called within a Wicket-managed request. If not (ie, if it's a Quartz job, or a Filter executed before Wicket's), the Application instance will not be available, and the injector won't know how to get the dependencies.
Another solution is to use Spring's #Configurable. It uses AspectJ to intercept creation of annotated objects, and inject its dependencies, even if you instantiate them directly with new (or some other framework, like Hibernate, creates them internally). But this requires runtime or build-time (works better for me) bytecode manipulation, which may be too much magic for some people.
#SpringBean only injects dependencies into classes that inherit from Wicket's Component. #Autowired only injects dependencies into classes created by Spring itself. That means you can't automatically inject a dependency into an object you create with new.
(Edit: you can also add a #SpringBean injection to your class by injecting in the constructor:
InjectorHolder.getInjector().inject(this);)
My normal workaround for this is to use my application class to help. (I'm a little puzzled by your use of new Application(...). I assume this isn't actually org.apache.wicket.Application.) For example:
public class MyApplication extends AuthenticatedWebApplication implements
ApplicationContextAware {
private ApplicationContext ctx;
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.ctx = applicationContext;
}
public static MyApplication get() {
return (MyApplication) WebApplication.get();
}
public static Object getSpringBean(String bean) {
return get().ctx.getBean(bean);
}
public static <T> T getSpringBean(Class<T> bean) {
return get().ctx.getBean(bean);
}
....
}
In my Spring application context:
<!-- Set up wicket application -->
<bean id="wicketApplication" class="uk.co.humboldt.Project.MyApplication"/>
My helper object then looks up the service on demand:
public class HelperObject {
private Service getService() {
return MyApplication.getSpringBean(Service.class);
}
The best practice would be to create your objects via a factory bean (that has those properties injected by Spring, and have that factory inject those properties to objects it spawns - pure IoC).
You should really avoid using SpringContext all over the place (or any other similar solution for that matter).
Here is a partial list of reasons:
Your code gets coupled with Spring way too much (low-cohesion).
You mix plumbing code with the business-logic.
Your code is less readable.
It's less maintainable (e.g., changing the name of the service bean would lead to code modification - this violates SRP & OCP).
It's less testable (e.g., you need the Spring framework to test it).