Nick Div
Nick Div

Reputation: 5628

How to create new Spring bean only for one particular class vs Singleton for rest of the application

I have an EmployeeService Spring Service class that I go around injecting everywhere in my application, e.g.

public class ClassX {

    @Bean
    EmployeeService employeeService;

}

public class ClassW {

    @Bean
    EmployeeService employeeService;

}

This is how EmployeeService bean looks like (Not sure if it is important for the answer)

public class EmployeeService {

    @Bean
    SalaryService salaryService;

    @Bean
    IdentificationService identificationService;

}

If I am not wrong, through out the application context the EmployeeService bean will be the same i.e. a Singleton (Unless defined otherwise)

But there is one place where I would like to use the EmployeeService bean that would not be shared by any other class. Let's say for e.g.

public class ClassY {

    @Bean
    EmployeeService employeeService;

}

Only in ClassY I want the bean to be a new one, not the one used by the rest of the application.

I am new to Spring so don't know how to exactly define what I am searching for as I am not completely familiar with the language and terms of the framework.

Please feel free to let me know if the question is not clear and any more information is needed.

P.S. I am using XML configuration for Spring and for the rest of the application i.e. apart from ClassY I would like the EmployeeService bean to be a Singleton only

Upvotes: 0

Views: 4299

Answers (5)

Sergii Bishyr
Sergii Bishyr

Reputation: 8641

You can define two different @Beans and distinguish it with using @Qualifier.

In Java config:

@Bean //This bean is singleton by default
@Qualifier("employeeServiceA")
public EmployeeService employeeServiceA() {
    new EmployeeService();
}

@Bean
@Qualifier("employeeServiceB")
@Scope("prototype")
public EmployeeService employeeServiceB() {
    new EmployeeService();
}

When @Autowired just the @Qualifier value that you need

@Autowired
@Qualifier("employeeServiceB")
private EmployeeService employeeService;

For XML configuration just define the id of the bean and then use this id as a @Qualifier value.

<bean id="employeeServiceA" class="com.package.to.EmployeeService">

<bean id="employeeServiceB" scope="prototype" class="com.package.to.EmployeeService">

There is also @Primary. Annotate the singleton bean with this annotation and you won't need to use @Qualifier to indicate that you need this bean to be injected. The same with XML config:

<bean id="employeeServiceA" primary="true" class="com.package.to.EmployeeService">

P.S. Do not use field injection. It's considered a bad practice. Use constructor injection instead.

Upvotes: 2

Fausto
Fausto

Reputation: 181

simple.. above the bean you want to be prototype add @Scope("prototype"):

public class ClassY {
@Scope("prototype")
@Bean
EmployeeService employeeService;
}

that instance will have a different scope

Upvotes: 0

Sundararaj Govindasamy
Sundararaj Govindasamy

Reputation: 8495

Only in ClassY I want the bean to be a new one, not the one used by the rest of the application.

As this instance will be used at only one class, Use the classic 'new' operator, Spring is NOT restricting you to do this, whenever necessary.

EmployeeService employeeService  = new EmployeeService();

Use @Autowired instead of @Bean to inject dependencies.

public class ClassX {

    @Autowired
    EmployeeService employeeService;

}

Upvotes: 0

Jaydeep Rajput
Jaydeep Rajput

Reputation: 3673

I am not able to understand why only in one class you want it not to be shared. There is something fishy in your Bean class, if the requirement is like that. If EmployeeService is thread-safe, it should be ok to be shared.

  • If your bean is thread-safe, you should use 'singleton' scope.
  • If you want to create new instance for every req, you should use 'prototype'.

So its design issue, if you want to achieve this.

But still Spring will support your requirements, define 2 beans of same class with diff names and use them by qualifier.

Upvotes: 0

venki
venki

Reputation: 1131

Use name attribute with the Bean annotation. Thus you can have two beans created for the same class. One will be singleton and the other one which is also singleton can be used exclusively with your class ClassY.

@Bean(name="secondBean")

Hope this will solve your problem.

Upvotes: 0

Related Questions