Using both annotation and XML config on one instance bean - java

I'm creating a service using annotation:
#Service
#Repository
public class UserServiceImpl implements UserService {
private String defaultPassword;
#Autowired
private UserRepository userRepository;
// ...
#Override
public void setDefaultPassword(String defaultPassword) {
this.defaultPassword = defaultPassword;
}
#Override
public String getDefaultPassword() {
return defaultPassword;
}
}
I want to configure defaultPassword value using Spring XML configuration not via annotation, so I added the following in XML definition:
<bean id="userServiceImpl" class="com.test.service.UserServiceImpl">
<property name="defaultPassword" value="youmustchangethis" />
</bean>
Then, I write test like:
public class UserServiceImplTest extends AbstractServiceImplTest {
#Autowired
private UserService userService;
// ...
}
I've matched the bean name in annotation and XML declaration (using bean id). My question is will userService variable in UserServiceImplTest always injected by the same singleton bean that configured in both XML and annotation? I've searched the documentation but didn't find explanation for 'hybrid' approach like this.

In this case bean defined in xml file will overwrite bean generated from annotation. That is because spring names annotation beans based on the class name with the first letter changed into lowercase. Unless you give it an explit name. There cannot exist two beans of the same name so xml definition overrides the annotation one.
You end up with one singleton called userServiceImpl here.

Related

What exactly does #autowired do in Springboot [duplicate]

I'm a little confused as to how the inversion of control (IoC) works in Spring.
Say I have a service class called UserServiceImpl that implements UserService interface.
How would this be #Autowired?
And in my Controllers, how would I instantiate an instance of this service?
Would I just do the following?
UserService userService = new UserServiceImpl();
First, and most important - all Spring beans are managed - they "live" inside a container, called "application context".
Second, each application has an entry point to that context. Web applications have a Servlet, JSF uses a el-resolver, etc. Also, there is a place where the application context is bootstrapped and all beans - autowired. In web applications this can be a startup listener.
Autowiring happens by placing an instance of one bean into the desired field in an instance of another bean. Both classes should be beans, i.e. they should be defined to live in the application context.
What is "living" in the application context? This means that the context instantiates the objects, not you. I.e. - you never make new UserServiceImpl() - the container finds each injection point and sets an instance there.
In your controllers, you just have the following:
#Controller // Defines that this class is a spring bean
#RequestMapping("/users")
public class SomeController {
// Tells the application context to inject an instance of UserService here
#Autowired
private UserService userService;
#RequestMapping("/login")
public void login(#RequestParam("username") String username,
#RequestParam("password") String password) {
// The UserServiceImpl is already injected and you can use it
userService.login(username, password);
}
}
A few notes:
In your applicationContext.xml you should enable the <context:component-scan> so that classes are scanned for the #Controller, #Service, etc. annotations.
The entry point for a Spring-MVC application is the DispatcherServlet, but it is hidden from you, and hence the direct interaction and bootstrapping of the application context happens behind the scene.
UserServiceImpl should also be defined as bean - either using <bean id=".." class=".."> or using the #Service annotation. Since it will be the only implementor of UserService, it will be injected.
Apart from the #Autowired annotation, Spring can use XML-configurable autowiring. In that case all fields that have a name or type that matches with an existing bean automatically get a bean injected. In fact, that was the initial idea of autowiring - to have fields injected with dependencies without any configuration. Other annotations like #Inject, #Resource can also be used.
Depends on whether you want the annotations route or the bean XML definition route.
Say you had the beans defined in your applicationContext.xml:
<beans ...>
<bean id="userService" class="com.foo.UserServiceImpl"/>
<bean id="fooController" class="com.foo.FooController"/>
</beans>
The autowiring happens when the application starts up. So, in fooController, which for arguments sake wants to use the UserServiceImpl class, you'd annotate it as follows:
public class FooController {
// You could also annotate the setUserService method instead of this
#Autowired
private UserService userService;
// rest of class goes here
}
When it sees #Autowired, Spring will look for a class that matches the property in the applicationContext, and inject it automatically. If you have more than one UserService bean, then you'll have to qualify which one it should use.
If you do the following:
UserService service = new UserServiceImpl();
It will not pick up the #Autowired unless you set it yourself.
#Autowired is an annotation introduced in Spring 2.5, and it's used only for injection.
For example:
class A {
private int id;
// With setter and getter method
}
class B {
private String name;
#Autowired // Here we are injecting instance of Class A into class B so that you can use 'a' for accessing A's instance variables and methods.
A a;
// With setter and getter method
public void showDetail() {
System.out.println("Value of id form A class" + a.getId(););
}
}
How does #Autowired work internally?
Example:
class EnglishGreeting {
private Greeting greeting;
//setter and getter
}
class Greeting {
private String message;
//setter and getter
}
.xml file it will look alike if not using #Autowired:
<bean id="englishGreeting" class="com.bean.EnglishGreeting">
<property name="greeting" ref="greeting"/>
</bean>
<bean id="greeting" class="com.bean.Greeting">
<property name="message" value="Hello World"/>
</bean>
If you are using #Autowired then:
class EnglishGreeting {
#Autowired //so automatically based on the name it will identify the bean and inject.
private Greeting greeting;
//setter and getter
}
.xml file it will look alike if not using #Autowired:
<bean id="englishGreeting" class="com.bean.EnglishGreeting"></bean>
<bean id="greeting" class="com.bean.Greeting">
<property name="message" value="Hello World"/>
</bean>
If still have some doubt then go through below live demo
How does #Autowired work internally ?
You just need to annotate your service class UserServiceImpl with annotation:
#Service("userService")
Spring container will take care of the life cycle of this class as it register as service.
Then in your controller you can auto wire (instantiate) it and use its functionality:
#Autowired
UserService userService;
Spring dependency inject help you to remove coupling from your classes.
Instead of creating object like this:
UserService userService = new UserServiceImpl();
You will be using this after introducing DI:
#Autowired
private UserService userService;
For achieving this you need to create a bean of your service in your ServiceConfiguration file. After that you need to import that ServiceConfiguration class to your WebApplicationConfiguration class so that you can autowire that bean into your Controller like this:
public class AccController {
#Autowired
private UserService userService;
}
You can find a java configuration based POC here
example.
There are 3 ways you can create an instance using #Autowired.
1. #Autowired on Properties
The annotation can be used directly on properties, therefore eliminating the need for getters and setters:
#Component("userService")
public class UserService {
public String getName() {
return "service name";
}
}
#Component
public class UserController {
#Autowired
UserService userService
}
In the above example, Spring looks for and injects userService when UserController is created.
2. #Autowired on Setters
The #Autowired annotation can be used on setter methods. In the below example, when the annotation is used on the setter method, the setter method is called with the instance of userService when UserController is created:
public class UserController {
private UserService userService;
#Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
}
3. #Autowired on Constructors
The #Autowired annotation can also be used on constructors. In the below example, when the annotation is used on a constructor, an instance of userService is injected as an argument to the constructor when UserController is created:
public class UserController {
private UserService userService;
#Autowired
public UserController(UserService userService) {
this.userService= userService;
}
}
In simple words Autowiring, wiring links automatically, now comes the question who does this and which kind of wiring.
Answer is: Container does this and Secondary type of wiring is supported, primitives need to be done manually.
Question: How container know what type of wiring ?
Answer: We define it as byType,byName,constructor.
Question: Is there are way we do not define type of autowiring ?
Answer: Yes, it's there by doing one annotation, #Autowired.
Question: But how system know, I need to pick this type of secondary data ?
Answer: You will provide that data in you spring.xml file or by using sterotype annotations to your class so that container can themselves create the objects for you.
Standard way:
#RestController
public class Main {
UserService userService;
public Main(){
userService = new UserServiceImpl();
}
#GetMapping("/")
public String index(){
return userService.print("Example test");
}
}
User service interface:
public interface UserService {
String print(String text);
}
UserServiceImpl class:
public class UserServiceImpl implements UserService {
#Override
public String print(String text) {
return text + " UserServiceImpl";
}
}
Output: Example test UserServiceImpl
That is a great example of tight coupled classes, bad design example and there will be problem with testing (PowerMockito is also bad).
Now let's take a look at SpringBoot dependency injection, nice example of loose coupling:
Interface remains the same,
Main class:
#RestController
public class Main {
UserService userService;
#Autowired
public Main(UserService userService){
this.userService = userService;
}
#GetMapping("/")
public String index(){
return userService.print("Example test");
}
}
ServiceUserImpl class:
#Component
public class UserServiceImpl implements UserService {
#Override
public String print(String text) {
return text + " UserServiceImpl";
}
}
Output: Example test UserServiceImpl
and now it's easy to write test:
#RunWith(MockitoJUnitRunner.class)
public class MainTest {
#Mock
UserService userService;
#Test
public void indexTest() {
when(userService.print("Example test")).thenReturn("Example test UserServiceImpl");
String result = new Main(userService).index();
assertEquals(result, "Example test UserServiceImpl");
}
}
I showed #Autowired annotation on constructor but it can also be used on setter or field.
The whole concept of inversion of control means you are free from a chore to instantiate objects manually and provide all necessary dependencies.
When you annotate class with appropriate annotation (e.g. #Service) Spring will automatically instantiate object for you. If you are not familiar with annotations you can also use XML file instead. However, it's not a bad idea to instantiate classes manually (with the new keyword) in unit tests when you don't want to load the whole spring context.
Keep in mind that you must enable the #Autowired annotation by adding element <context:annotation-config/> into the spring configuration file. This will register the AutowiredAnnotationBeanPostProcessor which takes care the processing of annotation.
And then you can autowire your service by using the field injection method.
public class YourController{
#Autowired
private UserService userService;
}
I found this from the post Spring #autowired annotation

Spring annotations confusion

i am really confused with spring annotations.
where to use # Autowired, where class is # Bean or # Component,
i understand we cannot use
Example example=new Example("String");
in Spring
but how alone
#Autowired
Example example;
will solve the purpose?
what about Example Constructor ,how spring will provide String value to Example Constructor?
i went through one of the article but it does not make much sense to me.
it would be great if some one can give me just brief and simple explanation.
Spring doesn't say you can't do Example example = new Example("String"); That is still perfectly legal if Example does not need to be a singleton bean. Where #Autowired and #Bean come into play is when you want to instantiate a class as a singleton. In Spring, any bean you annotate with #Service, #Component or #Repository would get automatically registered as a singleton bean as long as your component scanning is setup correctly. The option of using #Bean allows you to define these singletons without annotating the classes explicitly. Instead you would create a class, annotate it with #Configuration and within that class, define one or more #Bean definitions.
So instead of
#Component
public class MyService {
public MyService() {}
}
You could have
public class MyService {
public MyService() {}
}
#Configuration
public class Application {
#Bean
public MyService myService() {
return new MyService();
}
#Autowired
#Bean
public MyOtherService myOtherService(MyService myService) {
return new MyOtherService();
}
}
The trade-off is having your beans defined in one place vs annotating individual classes. I typically use both depending on what I need.
You will first define a bean of type example:
<beans>
<bean name="example" class="Example">
<constructor-arg value="String">
</bean>
</beans>
or in Java code as:
#Bean
public Example example() {
return new Example("String");
}
Now when you use #Autowired the spring container will inject the bean created above into the parent bean.
Default constructor + #Component - Annotation is enough to get #Autowired work:
#Component
public class Example {
public Example(){
this.str = "string";
}
}
You should never instantiate a concrete implementation via #Bean declaration. Always do something like this:
public interface MyApiInterface{
void doSomeOperation();
}
#Component
public class MyApiV1 implements MyApiInterface {
public void doSomeOperation() {...}
}
And now you can use it in your code:
#Autowired
private MyApiInterface _api; // spring will AUTOmaticaly find the implementation

Does Spring #Autowired inject beans by name or by type?

I am reading beginning spring (wiley press) book. In chapter 2 there is an example
about Java configuration and #Autowired. It provides this #Configuration class
#Configuration
public class Ch2BeanConfiguration {
#Bean
public AccountService accountService() {
AccountServiceImpl bean = new AccountServiceImpl();
return bean;
}
#Bean
public AccountDao accountDao() {
AccountDaoInMemoryImpl bean = new AccountDaoInMemoryImpl();
//depedencies of accountDao bean will be injected here...
return bean;
}
#Bean
public AccountDao accountDaoJdbc() {
AccountDaoJdbcImpl bean = new AccountDaoJdbcImpl();
return bean;
}
}
and this regular bean class
public class AccountServiceImpl implements AccountService {
#Autowired
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
...
}
When I run the code, it works. But I expected an exception because I have defined 2 beans with the same type in the configuration.
I realized it works like this:
if Spring encounters multiple beans with same type it checks field name.
if it finds a bean with the name of the target field, it injects that bean into the field.
Isn't this wrong? Is there a bug in Spring's handling of Java configuration?
The documentation explains this
For a fallback match, the bean name is considered a default qualifier
value. Thus you can define the bean with an id "main" instead of the
nested qualifier element, leading to the same matching result.
However, although you can use this convention to refer to specific
beans by name, #Autowired is fundamentally about type-driven injection
with optional semantic qualifiers. This means that qualifier values,
even with the bean name fallback, always have narrowing semantics
within the set of type matches; they do not semantically express a
reference to a unique bean id
So, no, it's not a bug, that is the intended behavior. The bean id (name) will be used as a fallback if a by-type autowiring doesn't find a single matching bean.

Autowire Bean with no default constructor, using config annotation

I have this Repository class which I wish to Autowire in a unit test. I'm currently getting the "no default constructor" error when running the test.
The class in question has no default constructor, I'm new to spring so may not have created the Bean correctly in the config class.
Below is the Bean in question (has no default constructor)
#Repository
public class GenericDaoImpl<T extends AbstractEntity> implements GenericDao<T> {
The config class
#Configuration
#EnableAspectJAutoProxy
#ComponentScan(basePackages = "com.example")
public class AppConfig {
#Bean
GenericDaoImpl<AbstractEntity> genericDoaIpm(final Class<AbstractEntity> tClass) {
return new GenericDaoImpl<AbstractEntity>(tClass);
}
}
And in the test I have:
#Autowired
private GenericDaoImpl<AbstractEntity> genericDaoImpl;
Is there something I'm missing or doing wrong here?
According to this and this, you only need to mark your constructor with #Autowired.
GenericDaoImpl.java
#Autowired
public GenericDaoImpl(Class<?> tClass) {
...
}
You can apply #Autowired to constructors as well. A constructor #Autowired annotation indicates that the constructor should be autowired when creating the bean, even if no elements are used while configuring the bean in XML file

Spring Injection not working in different service class

I have class
#Service("registrationService")
#Transactional
public class RegistrationService {
#Resource(name="registrationDAO")
public RegistrationDAO registrationDAO;
In the Controller i can access registrationService and registrationDAO with no problem.
I have another class
#Service("securityService")
public class SecurityService implements UserDetailsService {
protected static Logger logger = Logger.getLogger("service");
#Resource(name="registrationDAO")
public RegistrationDAO registrationDAO;
public String test(){
logger.debug(registrationDAO.findUserByID(1) );
return "Testing";
}
Now if i call test function in controller then it gives null pointer exception on registrationDAO
All your #Service, #Repository, #Controller, #Component (etc.) annotated class must be spring-managed for autowiring to work. Make sure they are picked up by spring classpath scanning:
<context:component-scan base-package="com.company" />
In some cases #Autowire, which does autowiring by type, can be useful to avoid the name argument you're supplying with the #Resource.

Categories