Choice between Autowired and using static field - spring

I have a single configuration bean that has the app's configuration settings. I want to expose this bean to any java class in my application. Do i autowire it to every class that need the bean or do i set it to a static field in some global class to make it conveniently accessible to every class? Is autowiring reasonable/recommended for high turnover objects? In my case this would be some network events coming in multiples every second.

I've used this approach with AspectJ compile-time (or load-time) weaving:
public final class Config {
public static String oneParticularSetting() {
return new ConfigHolder().oneParticularSetting;
}
#Configurable
private static class ConfigHolder {
#Value("${oneParticularSetting}")
private String oneParticularSetting;
}
}
Autowiring overhead/performance is something you'll just have to test.
Or you could reuse the ConfigHolder instance (taking thread safety into consideration).

Related

Dependency injection through constructor vs property [duplicate]

So since I've been using Spring, if I were to write a service that had dependencies I would do the following:
#Component
public class SomeService {
#Autowired private SomeOtherService someOtherService;
}
I have now run across code that uses another convention to achieve the same goal
#Component
public class SomeService {
private final SomeOtherService someOtherService;
#Autowired
public SomeService(SomeOtherService someOtherService){
this.someOtherService = someOtherService;
}
}
Both of these methods will work, I understand that. But is there some advantage to using option B? To me, it creates more code in the class and unit test. (Having to write constructor and not being able to use #InjectMocks)
Is there something I'm missing? Is there anything else the autowired constructor does besides add code to the unit tests? Is this a more preferred way to do dependency injection?
Yes, option B (which is called constructor injection) is actually recommended over field injection, and has several advantages:
the dependencies are clearly identified. There is no way to forget one when testing, or instantiating the object in any other circumstance (like creating the bean instance explicitly in a config class)
the dependencies can be final, which helps with robustness and thread-safety
you don't need reflection to set the dependencies. InjectMocks is still usable, but not necessary. You can just create mocks by yourself and inject them by simply calling the constructor
See this blog post for a more detailed article, by one of the Spring contributors, Olivier Gierke.
I will explain you in simple words:
In Option(A), you are allowing anyone (in different class outside/inside the Spring container) to create an instance using default constructor (like new SomeService()), which is NOT good as you need SomeOtherService object (as a dependency) for your SomeService.
Is there anything else the autowired constructor does besides add code
to the unit tests? Is this a more preferred way to do dependency
injection?
Option(B) is preferred approach as it does NOT allow to create SomeService object without actually resolving the SomeOtherService dependency.
Please note, that since Spring 4.3 you don't even need an #Autowired on your constructor, so you can write your code in Java style rather than tying to Spring's annotations.
Your snippet would look like that:
#Component
public class SomeService {
private final SomeOtherService someOtherService;
public SomeService(SomeOtherService someOtherService){
this.someOtherService = someOtherService;
}
}
Good to know
If there is only one constructor call, there is no need to include an #Autowired annotation. Then you can use something like this:
#RestController
public class NiceController {
private final DataRepository repository;
public NiceController(ChapterRepository repository) {
this.repository = repository;
}
}
... example of Spring Data Repository injection.
Actually, In my experience, The second option is better. Without the need for #Autowired. In fact, it is wiser to create code that is not too tightly coupled with the framework (as good as Spring is). You want code that tries as much as possible to adopt a deferred decision-making approach. That is as much pojo as possible, so much such that the framework can be swapped out easily.
So I would advise you create a separate Config file and define your bean there, like this:
In SomeService.java file:
public class SomeService {
private final SomeOtherService someOtherService;
public SomeService(SomeOtherService someOtherService){
this.someOtherService = someOtherService;
}
}
In ServiceConfig.java file:
#Config
public class ServiceConfig {
#Bean
public SomeService someService(SomeOtherService someOtherService){
return new SomeService(someOtherService);
}
}
In fact, if you want to get deeply technical about it, there are thread safety questions (among other things) that arise with the use of Field Injection (#Autowired), depending on the size of the project obviously. Check this out to learn more on the advantages and disadvantages of Autowiring. Actually, the pivotal guys actually recommend that you use Constructor injection instead of Field Injection
I hope I won't be downgraded for expressing my opinion, but for me option A better reflects the power of Spring dependency injection, while in the option B you are coupling your class with your dependency, in fact you cannot instantiate an object without passing its dependencies from the constructor. Dependency Injection have been invented for avoid that by implementing Inversion of Control,so for me option B doesn't have any sense.
Autowired constructors provides a hook to add custom code before registering it in the spring container. Suppose SomeService class extends another class named SuperSomeService and it has some constructor which takes a name as its argument. In this case, Autowired constructor works fine. Also, if you have some other members to be initialized, you can do it in the constructor before returning the instance to spring container.
public class SuperSomeService {
private String name;
public SuperSomeService(String name) {
this.name = name;
}
}
#Component
public class SomeService extends SuperSomeService {
private final SomeOtherService someOtherService;
private Map<String, String> props = null;
#Autowired
public SomeService(SomeOtherService someOtherService){
SuperSomeService("SomeService")
this.someOtherService = someOtherService;
props = loadMap();
}
}
I prefer construction injection, just because I can mark my dependency as final which is not possible while injecting properties using property injection.
your dependencies should be final i.e not modified by program.
There are few cases when #Autowired is preferable.
One of them is circular dependency. Imagine the following scenario:
#Service
public class EmployeeService {
private final DepartmentService departmentService;
public EmployeeService(DepartmentService departmentService) {
this.departmentService = departmentService;
}
}
and
#Service
public class DepartmentService {
private final EmployeeService employeeService;
public DepartmentService(EmployeeService employeeService) {
this.employeeService = employeeService;
}
}
Then Spring Bean Factory will throw circular dependency exception. This won't happen if you use #Autowired annotation in both beans. And this is understandable: the constructor injection happens at very early stage of Spring Bean initialization, in createBeanInstance method of Bean Factory, while #Autowired-based injection happens way later, on post processing stage and is done by AutowiredAnnotationBeanPostProcessor.
Circular dependency is quite common in complex Spring Context application, and it needs not to be just two beans referring one another, it could a complex chain of several beans.
Another use case, where #Autowired is very helpful, is self-injection.
#Service
public class EmployeeService {
#Autowired
private EmployeeService self;
}
This might be needed to invoke an advised method from within the same bean. Self-injection is also discussed here and here.
There is a way to inject the dependencies through constructor using #RequeiredArgsContructor annotation from Lombok
#RequiredArgsConstructor
#Service
class A {
private final B b // needs to be declared final to be injected
}
In this way you don't need to specify a constructor

Inject/Access Spring Bean into Log4j2 Plugin

I have a configuration properties class that I want to inject into a custom log4j2 RewritePolicy.
e.g.
#Plugin(name = "MyPolicy", category = "Core", elementType = "rewritePolicy", printObject = true)
public class MyPolicy implements RewritePolicy {
private MyPolicyProperties myPolicyProperties; // <-- want to inject/autowire this
public MyPolicy() {}
#PluginFactory
public static MyPolicy createPolicy() {
return new MyPolicy();
}
#Override
public LogEvent rewrite(LogEvent logEvent) {
// do something with myPolicyProperties here
return Log4jLogEvent.newBuilder()
.setLoggerName(logEvent.getLoggerName())
.setMarker(logEvent.getMarker())
.setLoggerFqcn(logEvent.getLoggerFqcn())
// ... etc
.build();
}
}
#ConfigurationProperties("app.mypolicy")
#Getter
#Setter
public class MyPolicyProperties {
private String property1;
private int property2;
// ... etc
}
I've tried implementing an ApplicationListener to reconfigure log4j as described here but was can't seem to get the appender and/or rewritepolicy to configure. Also tried implementing ApplicationContextAware described here but also didn't work.
Is there anyway to access the MyPolicyProperties in MyPolicy?
It can be done but it is almost never pretty. This is because Log4j Plugins are loaded by Log4j's plugin system while Spring Beans are loaded by Spring. Furthermore, they are not instantiated at the same time.
If you are using Spring Boot the very first thing that will happen is for Log4j2 to initialize because SpringApplication requests a Logger. So there would be no way to resolve the Spring Bean at that point as it doesn't exist. Later, Spring's bootstrap process will initialize Log4j again and then during application setup it will initialize once or twice more. During these subsequent initializations the bean may be available.
Depending on the type of application you are using you may be able to locate Spring's ApplicationContext so that you can call getBean() and inject it.
There is no automatic way to do this via an annotation or something similar.
The simplest way to do it is to either add a static method in the target class that gets initialized to reference itself when Spring is initialized or to create another class with a method that initializes a static method to reference the Spring created bean. So Spring will cause these static methods to reference the bean it creates. Then have your Log4j plugin call that static method to get the bean reference. Once it is non-null you can save it in the plugin and after that it should function as you want.

What is the magic behind Field #Autowired

I am currently improving my Spring knowledge. I wonder what really happens when I use Spring annotation #Autowire on a field.
Here is a piece of code :
OutputHelper file
#Component
public class OutputHelper {
#Autowired
#Qualifier("csvOutputGenerator")
private IOutputGenerator outputGenerator;
public void setOutputGenerator(IOutputGenerator outputGenerator) {
this.outputGenerator = outputGenerator;
}
// I can focus only on what my code do because my objects are injected
public void generateOutput(){
outputGenerator.generateOutput();
}
}
CsvOutputGenerator file
#Component
public class CsvOutputGenerator implements IOutputGenerator {
public void generateOutput(){
System.out.println("Csv Output Generator");
}
}
Application file
public static void main(String[] args) {
// Create the spring context
ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/spring-module.xml");
// Get the configured OutpuHelper from the spring-module.xml
OutputHelper output = (OutputHelper) context.getBean("outputHelper");
// Display output from the output configured
output.generateOutput();
}
My configuration file just contain <context:component-scan base-package="com.xxx.xxx.output"/>
When I execute this code all work fine. But what makes me surprised is when I delete the setOutputGenerator in OutPutHelper file, my piece of code keeps working. I tought that with this configuration, the OutputHelper was first created with default constructor and initialized with setter.
I expected an error because the variable outputGenerator was not be able to be initialized.
Is anyone can help me to understand ?
The idea to have fields #Autowired is questionable. It works, but it will difficult other aspects of your implementation (i.e. testing).
There are 3 types of injections:
fields - basically configured applying reflection (Field.set(Object, Object)) directly to the field:
#Autowired
private MyInterface field;
setters - with this approach the configuration of each dependency goes through a property (spring goes through all methods and execute each one annotated with #Autowired using Method.invoke(Object, Object...), thus its value is configured using its setter as follows:
#Autowired
public void setField(MyInterface value) {
this.field = value;
}
constructors - the last, and my preferable approach, the constructor injection. That one basically annotates an constructor with #Autowired and instead of using methods or fields, you can configure your bean directly on your constructor. For that spring will elect the a constructor to be used to instantiate your #Component, and it will use an #Autowired if existent or a empty params constructor, invoking it using Constructor.newInstance(Object...). Example:
#Component
public class Implementation {
private MyInterface field;
#Autowired
public Implementation(MyInterface value) {
Assert.notNull(value, "value should not be null");
this.field = value;
}
}
One of the ideas behind Inversion of Control (or Dependence Injection) is to be able to isolate a piece of code in order to provide decent test implementation support.
In order to go deeper, it is necessary to comment that during a unit test you want the class in its isolated form, all you will use with that class are basically mocks for its dependencies (injections).
So, what are the results:
If you do field injection, it will be quite costly to every single time set the beans using some reflection to configure the bean during your tests (another logic needs to be introduced to configure the bean to be tested).
With setter injection approach you will be able to use your own bean to configure it with mocks necessary to isolate your implementation and test its functionality.
And finally, with the constructor injection approach you will have not only the support to configure your bean, but you will be able to require its dependencies. This means that for every new dependency a new parameter on your constructor is added, this brings you come advantages on development time, for example, you will be able to see on development time the unit tests affected with the introduction of that new dependency (once your IDE will point it out for your).
Simple answer
Actually, the setter is useless, since the CDI use java Reflection to access fields.
It means that fields are no longer accessed by method calls.
Reflection allow iterating throught all fields of a class and check if there are annoted with a specific annotation.
In this case, if a field in your class is annoted With #Autowired (or #Inject wich is more J2E complient), the container will iterate throught searching if there is a registered bean that fits the current property.
Going deeper
When you context is starting, the container iterate classes and search all field annoted with #Inject or #Autowired.
For these fields, it search an available bean.
Here is the must simple example :
public class SpringClassInChargeOfDependencyInjection {
public void handdleInjections(T objectWithInjectableField) {
Class<T> clazz = objectWithInjectableField.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Autowired.class) || field.isAnnotationPresent(Inject.class)) {
//find a bean for the type;
Object injectableBean = getAvailablebean(field.getType());
field.setAccessible(true);
//inject the value into the class, this line explain why the setter is not necessary
field.set(objectWithInjectableField, injectableBean);
}
}
}
}
This is a non-working example just to explain how it works.
Tips
You might consider using #Inject instead of #Autowired, the later was created by Spring, #Inject is a part of the the JSR-330. Spring does understand #Inject as well, you just need to add the javax.inject jar dependency to your project. If later you want to switch from spring to something else (guice for example) you won't have to change all your #Autowired annotations
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>

How can I make sure a "pool" bean gets all the other beans it needs?

I have a spring config where I define hundreds of actions which extend MyAction. I have a pool where an execution service can look up actions. I can't use the appContext directly because each action has one or more "keys" which the execution service will use and pool cuts that dependency.
So the pool must be able to collect all beans of type MyAction (or rather beans that extend MyAction).
The method ApplicationContext.getBeansOfType() seems to do what I need but when can I safely call it?
It would be great if I could call it in a #PostConstruct method but is it guaranteed that the bean factory has seen added each and every bean from the config at that time?
Note: Almost all of my beans are #Lazy
You could use injection by constructor and passing a Collection of yours MyAction
Something like
#Component
public class Foo {
private final Set<MyAction> myActions;
#Inject
public Foo(Set<MyAction> myActions) { this.myActions = myActions; }
}
or
public class Foo {
private Set<MyAction> myActions;
#Inject
public void setMyActions(Set<MyAction> myActions) { this.myActions = myActions; }
}
Spring will take care of creating the set with all beans that extends MyAction.
In the first case, they are injected by constructor, you can safely use them in any method.
In the second case, Spring will eventually call the setter. You can either do any post processing in the setter or add a #PostConstruct method that works on myActions.
Try to use ListableBeanFactory like this. Also here is API documentation. Method getBeansOfType has parameter allowEagerInit which forces eager init of lazy object.

Autowiring doubts in spring?

After going thru autowiring concept
i have got some questions. These are:-
If i need to autowire below class byType or byName , is it mandatory to have setStudent() method in class College?
public class College {
private Student student1;
private String registration1;
}
<bean id="student1" class="Student"/> - in case of byname it will look into id attribute and in case of bytype it will look for class attribute in above
Stetement. Right? If incase it finds two bean dean tags for the same type it will throw fatal error in case of bytype. Correct?
autodetect Scenario chooses constructor or byType through introspection of the bean class. If a default constructor is found, the byType mode
will be applied.
My question here if default constructor is not found and constructor with argument is found then autowire by constructor
will be applied. Correct?
Do we need to specify #Autowired somewhere in College to apply the autowiring. As i can see this in this example
but nothing is specified here
1), 4) There are two separate ways of autowiring in Spring: XML-based and annotaion-based.
XML-based autowiring is activated from XML config, as described here. In the end, it will call setter method, so setStudent() method is required here.
Annonation-based autowiring, on the other hand, is performed via reflection magic. It attempts to fill everything you mark with #Autowired annotation. In fact, it can set private field with no accessors, as in
public class Foo {
#Autowired private Thingy thing; // No getThing or setThing methods
private void doStuff() {
// thing is usable here
}
}
For #Autowired annotaion to work, you will need to define corresponding bean post-processor; it is done by adding the following line to xml config:
<context:annotation-config/>
Note, that these two autowiring methods are independant, and it is possible(but not recommended) to use them simultaneously. In that case, xml autowiring will override annotations.
2) In general, autowiring will fail, if it cannot find one and only one candidate for injection. So, in your case, it will fail with exception upon container creation. There are some fallback quirks, but in general it works reliably.
3) Yes, documentaion says so.
About byName and byType autowiring. While byName autowiring simply tries to match bean name (can be specified with id attribute), byType is a bit more complex than class attribute lookup. It searches beans by type, and it will match interfaces. Example:
public interface SomeService {
void doStuff();
}
public class SomeServiceImpl implements SomeService {
#Override public void doStuff() {
// Implementation
};
}
public class ServiceUser {
#Autowired
private SomeService someService; // SomeServiceImpl instance goes here
}
P.S. You are referencing two different versions of Spring in your question, 2.5 and 3.0. Autowiring behavior is same in both.
In Addition if you are using #Autwired annotation you need to mark the classes as candidates for autowiring. It should be done by using one of these annotations:
#Repository
#Service
#Component
#Controller
and of cause you can configure it in different scopes:
#Scope("prototype")
#Repository
public class MovieFinderImpl implements MovieFinder {
// ...
}
Hope it makes it more clear.

Resources