Is it possible to attach BeanPostProcessor with specific bean initilzation - spring

I am wondering if it is possible to define a BeanPostProcessor class which can only be executed for specific beans.
As per configuration, I can have 2 beans like as mentioned below. Here InitHelloWorld is implementing BeanPostProcessor. postProcessBeforeInitialization and postProcessAfterInitialization methods are overwritten here. These methods gets called for all the bean initialized. I want these methods being called only for com.tutorialspoint.HelloWorld
<bean id="helloWorld" class="com.tutorialspoint.HelloWorld"
init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"/>
</bean>
<bean id="helloWorld1" class="com.tutorialspoint.HelloWorld1"
init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"/>
</bean>
<bean class="com.tutorialspoint.InitHelloWorld" />

Consider to use some marker annotation on those classes:
public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
Class<?> targetClass = AopUtils.getTargetClass(bean);
if (AnnotationUtils.findAnnotation(beanClass, MyMarker.class) != null) {
....
return bean;
}
return bean;
}

Try checking the class itself when defining the method something like:
public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
if (bean.getClass().equals(HelloWorld.class)) {
ReflectionUtils.doWithFields(bean.getClass(), new FieldCallback() {
......
}

A simple if-statement that checks the class instance in the postProcessor initialization will do the trick, that is:
if (bean instanceof HelloWorld){...}
or
if (bean.getClass().equals(HelloWorld.class)){...}
To put it in context:
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof HelloWorld){
System.out.println("This only prints for an instance of HelloWord");
}

Related

Replace Private Method of Spring Bean

i have requirement to replace private method of spring bean, can i achieve through spring replace.
My Code :
Replacer Class :
public class PrivateCarRep extends Car implements MethodReplacer{
#Override
public Object reimplement(Object obj, Method method, Object[] args) throws
Throwable {
// new property of Car.breaks() method.
System.out.println("New privateBreaksIs Done from Shiv");
return obj;
}
}
Car.java
package org.websparrow.beans;
public class Car {
private void privateBreaks() {
System.out.println("Old car break. privateBreaks");
}
}
My Spring Configuration:
<bean id="PrivateCarRep" class="org.websparrow.beans.PrivateCarRep"/>
<bean id="car" class="org.websparrow.beans.Car">
<replaced-method name="privateBreaks" replacer="PrivateCarRep" />
</bean>
Dear All,
i already know that i can't replace private method through spring replacer but is there any workaround for this in spring..
You need to define PrivateCarRep as a bean:
<bean id="privateCarReplacer" class="com.xx.yy.zz.PrivateCarRep" />
<bean id="car" class="org.websparrow.beans.Car">
<replaced-method name="privateBreaks" replacer="privateCarReplacer" />
</bean>
I'm afraid you can't do that,I thing the method should be be protected or public.

Spring AOP : Can we access bean object by getBean("beanName") method after applying ProxyFactoryBean on that Bean?

I have applied a 'BeforeAdvice' through 'ProxyFactoryBean' on a Bean of type "MyXMLApplication" now I am not able to access the Bean object directly{by getBean(MyXMLApplication.class)}, it is giving error :-
by setter dependency injection myxml
Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.journaldev.spring.di.consumer.MyXMLApplication] is defined: expected single matching bean but found 2: MyXMLApp,proxy
However I am able to get the bean object by "proxy" bean object{(MyXMLApplication)context.getBean("proxy")}. Now my question is after applying proxy on any bean is there any way to access it directly without proxy bean.
My code is:
********Before Advisor*********
public class MyBeforeAdvisor implements MethodBeforeAdvice{
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
// TODO Auto-generated method stub
System.out.println("before advice run");
}
}
*********applicationContext.xml********
<bean id="twitter" class="com.journaldev.spring.di.services.TwitterService"></bean>
<bean id="MyXMLApp" class="com.journaldev.spring.di.consumer.MyXMLApplication" autowire="byType"/>
<bean id="beforeAdvice" class="com.journaldev.spring.aop.advisor.MyBeforeAdvisor"></bean>
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="MyXMLApp"></property>
<property name="interceptorNames">
<list>
<value>beforeAdvice</value>
</list>
</property>
</bean>
**********Main Bean Class************
public class MyXMLApplication {
private MessageService service;
public void setService(MessageService svc){
System.out.println("by setter dependency injection myxml");
this.service=svc;
}
public boolean processMessage(String msg, String rec) {
return this.service.sendMessage(msg, rec);
}
}
**********Autowired Bean Interface *******
public interface MessageService {
boolean sendMessage(String msg, String rec);
}
**********Autowired Bean Impl*********
public class TwitterService implements MessageService {
public boolean sendMessage(String msg, String rec) {
System.out.println("Twitter message Sent to "+rec+ " with Message="+msg);
return true;
}
}
************* Main function**********
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
MyXMLApplication app = context.getBean(MyXMLApplication.class); --> Not Working
//MyXMLApplication app = (MyXMLApplication)context.getBean("proxy"); -->working
app.processMessage("Hi", "abc#abc.com");
context.close();
}
Sorry guys, the error was coming because I was calling getBean(MyXMLApplication.class) [by type] that is why it founds two beans "proxy" and "MyXMLApp" of type MyXMLApplication.class and giving the error.
It is not something like we can not call the 'getBean'method on bean directly after applying any proxy on that.

which scope has a bean that is created through a singleton factory bean

I have defined the following beans:
<bean id="factoryBean" class="com.example.MyFactory" factory-method="getMyBean"/>
<bean id="myBeanSession" class="com.example.bean.impl.myBeanSessionImpl" scope="session" lazy-init="true">
<aop:scoped-proxy/>
</bean>
<bean id="myBeanNoSession" class="com.example.bean.impl.myBeanNoSessionImpl" scope="prototype" lazy-init="true"/>
MyFactory.java:
public abstract class MyFactory{
public static MyBean getMyBean(){
MyBean myBean=null;
try{
myBean=(MyBean)Application.getBean("MyBeanSession");
} catch (RuntimeException e) {
if (e instanceof IllegalStateException ||
e instanceof BeanCreationException) {
myBean=(MyBean )Application.getBean("MyBeanNoSession");
} else
throw e;
}
return myBean;
}
factoryBean is a singleton, myBeanSession is session, and myBeanNoSession is prototype.
If no exceptions are thrown, so myBeanSession is created through getMyBean method, which scope has the bean that is created?
In the test that we are doing seems that it is a singleton scope bean, instead of session scope.
Bean will have session or prototype scope, but never singleton.

How can we switch between different Implementations in Spring Context XML with an Boolean?

How can we switch between different Implementations in Spring Context XML with an Boolean?
for example:
<bean id="detailsController" class="com.something.detailsController" >
if true then
<property name="dao" ref="firstDao"/>
else
<property name="dao" ref="secoundDao"/>
I know in Spring3 we can work with profiles
You could do that by modifying your Java code and use Spring EL together with ApplicationAware and InitializingBean.
public class DetailsController implements ApplicationContextAware, InitializingBean {
private DetailsControllerDAO dao;
private String daoName;
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public void afterPropertiesSet() {
dao = applicationContext.getBean(daoName);
}
public void setDaoName(String daoName) {
this.daoName = daoName;
}
}
In XML:
<bean id="detailsController" class="com.something.detailsController">
<property name="daoName" value="#{myCondition ? 'firstDao' : 'secondDao'}" />
</bean>
Of course, this solution has the disadvantage to add dependency to Spring code in your controller. To avoid that, you could move that code in a proxy class, as described by Guillaume Darmont.
I dont think this can be done at the XML level.
Spring really cannot do that. See the bean lifecycle. Been classes are created, than properties are injected and than afterPropertiesSet() or #PostConstructor methods are invoked. Of course when I omit lazy initialized beans.
But if you want for testing etc. and so you need just the firstDao or the secondDao in your application at the sametime that depends just on your settings, you can use a bean factory. The bean factory creates your bean as you want. I also use it for to split development environment, test environment and production environment.
package com.dummyexample.config;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Factory bean to create real or test dao.
* The result depends on realDaoEnabled configuration parameter.
*
* #author Martin Strejc
*/
#Configuration
public class DaoBeanFactory {
// mapping to servlet context configuration
#Resource(mappedName = "realDaoEnabled")
private Boolean realDaoEnabled = true;
// TestDao extends or implements Dao
#Autowired
private TestDao testDao;
// ProdDao extends or implements Dao
#Autowired
private ProdDao prodDao;
public DaoBeanFactory() {
}
#Bean(name="dao")
public Dao getDao() {
if(realDaoEnabled) {
return prodDao;
}
return testDao;
}
}
Since your DAOs are exchangeable, they inherits the same type (abstract class or interface). Thus you can write a RoutingDetailsControllerDAO.
Let's say that your common interface is named DetailsControllerDAO, with two methods getDetails and getMoreDetails inside, the code would be :
public class RoutingDetailsControllerDAO implements DetailsControllerDAO {
private DetailsControllerDAO firstDAO;
private DetailsControllerDAO secondDAO;
protected DetailsControllerDAO getDAOToUse() {
return YOUR_BOOLEAN_CONDITION ? firstDAO : secondDAO;
}
#Override
public Details getDetails() {
return getDAOToUse().getDetails();
}
#Override
public Details getMoreDetails() {
return getDAOToUse().getMoreDetails();
}
// Insert firstDAO and secondDAO setters below
...
}
Your Spring XML config is now :
<bean id="detailsController" class="com.something.detailsController" >
<property name="dao" ref="routingDetailsControllerDAO"/>
</bean>
<bean id="routingDetailsControllerDAO" class="com.something.RoutingDetailsControllerDAO">
<property name="firstDao" ref="firstDao"/>
<property name="secondDao" ref="secondDao"/>
</bean>
Few possibilities:
You can either use profiles (<beans profiles="profileOne">).
You can use FactoryBean to create the correct DAO
You can use SPeL
The last one is the easiest:
<bean id="detailsController" class="com.something.detailsController">
<property name="dao" ref="#{condition ? 'firstDao' : 'secondDao'}" />
</bean>
Of course you can load bean name from properties file via property configurer:
<bean id="detailsController" class="com.something.detailsController">
<property name="dao" ref="${bean.name.from.properties.file}" />
</bean>

Accessing spring bean from logging appender class

I have log4j DailyRollingFileAppender class in which setFile() method I need to check database value to decide which file to used for logging.
DailyRollingFileAppender class
public void setFileName()
{
isLoginEnabled = authenticationManager.checkLoginLogging();
}
Here 'authenticationManager' is object of class used to make database call using spring dependency injection feature.
spring-beans.xml
<bean id="dailyRollingFileAppender" class="com.common.util.DailyRollingFileAppender">
<property name="authenticationManager">
<ref bean="authenticationManager"/>
</property>
</bean>
<bean id="authenticationManager" class="com.security.impl.AuthenticationManagerImpl">
<property name="userService">
<ref bean="userService"/>
</property>
</bean>
Now when I start my application log4j gets initiated first and since spring-beans is yet to invoked it throws NullPointerException in method setFileName().
So is there a way I can make call to 'authenticationManager.checkLoginLogging();' from DailyFileAppender class so that when log4j loads it should able to get database value?
A few years late, but I hope this is of help to someone.
I was after similar functionality - I have a custom appender, and i wanted to use an autowired bean to perform some logging using a service we'd built. By making the appender implement the ApplicationContextAware interface, and making the field that i'd normally autowire static, i'm able to inject the spring-controlled bean into the instance of the appender that log4j has instantiated.
#Component
public class SslErrorSecurityAppender extends AppenderSkeleton implements ApplicationContextAware {
private static SecurityLogger securityLogger;
#Override
protected void append(LoggingEvent event) {
securityLogger.log(new SslExceptionSecurityEvent(SecurityEventType.AUTHENTICATION_FAILED, event.getThrowableInformation().getThrowable(), "Unexpected SSL error"));
}
#Override
public boolean requiresLayout() {
return false;
}
#Override
public synchronized void close() {
this.closed = true;
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) {
if (applicationContext.getAutowireCapableBeanFactory().getBean("securityLogger") != null) {
securityLogger = (SecurityLogger) applicationContext.getAutowireCapableBeanFactory().getBean("securityLogger");
}
}
}

Resources