Dependency Injection into your Singleton - spring

I have a singleton that has a spring injected Dao (simplified below):
public class MyService<T> implements Service<T> {
private final Map<String, T> objects;
private static MyService instance;
MyDao myDao;
public void set MyDao(MyDao myDao) {
this. myDao = myDao;
}
private MyService() {
this.objects = Collections.synchronizedMap(new HashMap<String, T>());
// start a background thread that runs for ever
}
public static synchronized MyService getInstance() {
if(instance == null) {
instance = new MyService();
}
return instance;
}
public void doSomething() {
myDao.persist(objects);
}
}
My spring config will probably look like this:
<bean id="service" class="MyService" factory-method="getInstance"/>
But this will instantiate the MyService during startup.
Is there a programmatic way to do a dependency injection of MyDao into MyService, but not have spring manage the MyService?
Basically I want to be able to do this from my code:
MyService.getInstance().doSomething();
while having spring inject the MyDao for me.

Here is a solution, create a class with a static factory method:
public class MyService {
private static MyService instance;
private MyDao myDao;
public static MyService createInstance(final MyDao myDao) {
instance = new MyService(myDao);
return instance;
}
private MyService(final MyDao myDao) {
this.myDao = myDao;
}
public static synchronized MyService getInstance() {
return instance;
}
public void doSomething() {
// just do it!
myDao.justDoIt();
}
}
and use spring to initilize it:
<bean class="my.path.MyService" factory-method="createInstance" scope="singleton">
<constructor-arg ref="reference.to.myDao" />
</bean>
and now you should be able to do:
MyService.getInstance().doSomething();
without any problems.

If you want a singleton, why not just define that one class in the Spring configs, and it's automatically a singleton (by default).
To avoid initialising at start up, have you looked at Spring lazy initialisation ? Basically you need:
lazy-init="true"
in your bean definition.

As mentioned by others, you should let spring manage your singletons, but if you want to manage them yourself and just let spring inject dependencies, do this:
applicationContext.getAutowireCapableBeanFactory().autowireBean(yourService);

I believe the FactoryBean interface is a good alternative for you. It's a very good choice when you need to execute some initialization logic. For example to start an in memory database or some background processes in separate threads.
You can read more about it in the reference documentation.
An example that demonstrates how I instantiate a database and return a datasource everytime someone wants a bean from the FactoryBean implementation.
#PostConstruct
void init() {
embeddedDatabase = new EmbeddedDatabaseBuilder().addScript(schemaPath)
.addScript(dataPath).setType(embeddedDatabaseType).build();
}
public DataSource getObject() throws Exception {
return embeddedDatabase;
}
This enables loose coupling between the factory logic and the returned object. It's heavily used by the Spring framework internally.
If you want it to be initialized the first time you use it, then set lazy-initialization to true.
Another alternative if you want your code to interact with the Spring container is to create a factory that implements the ApplicationContextAware interface. Then you can do something like this:
myDao = context.getBean(MyDao.class);

Related

Dependency injection in custom evaluator in logback in spring boot

I am writing a custom evaluator in which I want to autowire another bean. I am unable to do so as evaluator gets initialized by logger where as beans are initialized by spring context. Below is the sample of my code:
In logback-spring.xml:
<appender name="myAppender" class="ch.qos.logback.classic.net.SMTPAppender">
<evaluator class="com.package.CustomEvaluator">
<marker>FATAL</marker>
<interval>1000000</interval>
</evaluator>
</appender>
My custom evaluator:
#Slf4j
#Component
public class CustomEvaluator extends OnMarkerEvaluator {
#Autowired
private MyService myService;
#Override
public boolean evaluate(ILoggingEvent event) throws EvaluationException {
\\logic goes here
}
}
I am getting object of MyService always as null(which is expected). Is there any work around for this?
It don't think its possible because the Evaluator being an internal logback abstraction is not managed / initialized by spring, so obviously spring can't autowire anything into the evaluator.
In addition note, that logback gets initialized even before application context starts.
Of course you could provide some global holder class for the application context and set the context to it in the main method, and then get the reference to it in this evaluator, something like this:
public class ApplicationContextHolder {
private static ApplicationContext context;
// call it in main() method
public static void setContext(ApplicationContext ctx) {context = ctx;}
public static ApplicationContext getContext() {return context;}
}
class CustomEvaluator extends OnMarkerEvaluator {
public boolean evaluate(ILoggingEvent event) throws EvaluationException {
ApplicationContext ctx = ApplicationContextHolder.getContext();
if(ctx == null) {return false;} // not yet initialized / accessible
MyService myService = ctx.getBean(MyService.class);
}
}
But all-in-all I believe its a very ugly solution.
As a suggestion, I think you should consider refactoring of the logic so that the decision of whether to send an email based on logging event will be taken in the application (which is, I assume, spring boot driven so you have an access to the MyService)
Given the current implementation:
public foo() {
LOGGER.info("This should be sent by email");
}
I suggest a part of application:
#Component
public class MyLogic {
#Autowired MyService myService;
public void foo() {
if(myService.shouldSend()) {
LOGGER.info("This should be sent by email");
}
}
}

Use spring Transactional in a Prototype bean

I would like to use spring transaction management capabilities within a prototype bean. I did the following:
I've used javax.inject.Provider to create my prototype bean.
I've annotated the method of the prototyped bean with the #Transactional annotation.
Is this the right way of doing it?
#Service
public class SomeService {
#Autowired
private Provider<SomePrototype> myPrototypeProvider;
public void execute() {
SomePrototype somePrototype = myPrototypeProvider.get();
somePrototype.someMethod();
}
}
#Component
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class SomePrototype {
#Autowired
private SomeSpringBean someSpringBean;
#Autowired
private SomeRepository someRepository;
#Transactional(propagation = Propagation.REQUIRED)
public void someMethod() {
Result result = someSpringBean.doSomething();
someRepository.save(result);
}
}
The initialisation of transaction-scoped bean requires a proxy. Therefore, if we define a transactional bean as prototype, every that bean is requested, a new proxy is created, and that is not efficient.
What is reason behind this requirement (to have transactional prototype bean)

how to avoid using context.getbean in spring

There have been several arguments around not using ApplicationContext.getBean() to get a bean reference, of which most are based on logic that it violates the principles of Inversion of control.
Is there a way to get reference to prototype scoped bean without calling context.getBean() ?
Consider to use Spring Boot!
Than you can do something like this...
Runner:
#SpringBootApplication
public class Runner{
public static void main(String[] args) {
SpringApplication.run(Runner.class, args);
}
}
Some Controller:
#Controller
public class MyController {
// Spring Boot injecting beans through #Autowired annotation
#Autowired
#Qualifier("CoolFeature") // Use Qualifier annotation to mark a class, if for example
// you have more than one concreate class with differant implementations of some interface.
private CoolFeature myFeature;
public void testFeature(){
myFeature.doStuff();
}
}
Some cool feature:
#Component("CoolFeature") // To identify with Qualifier
public class CoolFeature{
#Autowired
private SomeOtherBean utilityBean;
public void doStuff(){
// use utilityBean in some way
}
}
No XML files to handle.
We can still access context for manual configurations if needed.
Suggested reading:
Spring Boot Reference
Pro Spring Boot
This type of problem can be solved using method injection, which is described in more detail here: https://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-factory-method-injection
This is the most common approach to create prototype bean:
abstract class MyService {
void doSome() {
OtherService otherService = getOtherService();
}
abstract OtherService getOtherService();
}
#Configuration
class Config {
#Bean
public MyService myService() {
return new MyService() {
OtherService getOtherService() {
return otherService();
}
}
}
#Bean
#Scope("prototype")
public OtherService otherService() {
return new OtherService();
}
}

Java 8 and Spring 4 : Use autowiring in interface

Java 8 added a new feature by which we can provide method implementation in interfaces.
Is there any way in Spring 4 by which we can inject beans in the interface which can be used inside the method body?
Below is the sample code
public interface TestWiring{
#Autowired
public Service service;// this is not possible as it would be static.
//Is there any way I can inject any service bean which can be used inside testWiringMethod.
default void testWiringMethod(){
// Call method of service
service.testService();
}
}
This is a bit tricky but it works if you need the dependency inside the interface for whatever requirement.
The idea would be to declare a method that will force the implemented class to provide that dependency you want to autowire.
The bad side of this approach is that if you want to provide too many dependencies the code won't be pretty since you will need one getter for each dependency.
public interface TestWiring {
public Service getService();
default void testWiringMethod(){
getService().testService();
}
}
public class TestClass implements TestWiring {
#Autowire private Service service;
#Override
public Service getService() {
return service;
}
}
You can created Class utils of application context and use it everywhere even not bean class .
you can have code somethins this :
public class ApplicationContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext context) {
ApplicationContextUtil.applicationContext = context;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
}
and add this to your spring configuration
<bean class="com.example.ApplicationContextUtil" id="applicationContextUtil"/>
now simple to use when you need :
ApplicationContextUtil.getApplicationContext().getBean(SampleBean.class)
this word in web and simple spring app.

Proxy cannot be cast to CLASS

I'm using Spring for wiring dependencies specifically for DAO classes that use Hibernate, but I'm getting an exception that has me puzzled:
$Proxy58 cannot be cast to UserDao
My DAO is configured as follows:
<bean id="userDao" class="com.domain.app.dao.UserDao">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
And I have an interface, abstract base class and a final implementation as follows.
Interface:
public interface Dao {
public void save(Object object);
public Object load(long id);
public void delete(Object object);
public void setSessionFactory(SessionFactory sessionFactory);
}
Abstract Base Class:
public abstract class BaseDao implements Dao {
private SessionFactory sessionFactory;
#Transactional
#Override
public void save(Object object) {
PersistentEntity obj = (PersistentEntity) object;
currentSession().saveOrUpdate(obj);
}
#Transactional
#Override
public abstract Object load(long id);
#Transactional
#Override
public void delete(Object object) {
// TODO: this method!
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Session currentSession() {
return sessionFactory.getCurrentSession();
}
}
Implementation:
public class UserDao extends BaseDao implements Dao {
#Transactional(readOnly=true)
#Override
public Object load(long id) {
Object user = currentSession().get(User.class, id);
return user;
}
}
The following throws the exception mentioned above:
UserDao dao = (UserDao) context.getBean("userDao");
This, however, does not throw an exception:
Dao dao = (Dao) context.getBean("userDao");
If anyone can offer any assistance or guidance as to why this exception is happening, I would be very appreciative.
Spring uses JDK dynamic proxies by default ($Proxy58 is one of them), that can only proxy interfaces. This means that the dynamically created type $Proxy58 will implement one or more of the interfaces implemented by the wrapped/target class (UserDao), but it won't be an actual subclass of it. That's basically why you can cast the userDao bean to the Dao interface, but not to the UserDao class.
You can use <tx:annotation-driven proxy-target-class="true"/> to instruct Spring to use CGLIB proxies that are actual subclasses of the proxied class, but I think it's better practice to program against interfaces. If you need to access some methods from the proxied class which are not declared in one of it's interfaces, you should ask yourself first, why this is the case?
(Also, in your code above there are no new methods introduced in UserDao, so there is no point in casting the bean to this concrete implementation type anyway.)
See more about different proxying mechanisms in the official Spring reference.
I was writing unit tests and needed to be able to stub out the DAOs for some calls.
Per This guys post:
http://www.techper.net/2009/06/05/how-to-acess-target-object-behind-a-spring-proxy/
I used his method provided:
#SuppressWarnings({"unchecked"})
protected <T> T getTargetObject(Object proxy, Class<T> targetClass) throws Exception {
if (AopUtils.isJdkDynamicProxy(proxy)) {
return (T) ((Advised)proxy).getTargetSource().getTarget();
} else {
return (T) proxy; // expected to be cglib proxy then, which is simply a specialized class
}
}
Then you can easily call it with the proxy and get the object behind the proxy and manipulate the objects in it directly as needed.

Resources