Make a bean unautowireable or that disposes of it self? - spring

We need a spring bean that will either
Prevent the framework from #Autowired -ing it.
or
Once it does its work it destroys itself?
The bean roughly looks like this:
public final class Registrar implements ApplicationListener<SOFrameworkInitializedEvent>
So after it receives this 1 time event do the work and go away. We are using Spring 3.0.7.

Use the autowire-candidate property in the bean definition XML, e.g.:
<bean id="MyBean" class="com.acme.SimpleTestServiceImpl" autowire-candidate="false"/>

Related

what is the use of FACTORY_BEAN_PREFIX = "&" in BeanFactory?

i am new to spring and want to know the purpose of FACTORY_BEAN_PREFIX = "&" field of bean factory. Anyone please explain.
The Spring Framework for Dependency Injection provides some component to encapsulate complex objects initialization and population. It is FactoryBean. So, you can do something like this:
<bean id="myBean" class="com.my.proj.MyBeanFactoryBean"/>
Where MyBeanFactoryBean creates and return MyBean. From here Spring container populates MyBean object under myBean id.
But for some reason the MyBeanFactoryBean is populated to the container as a bean, too.
And here FACTORY_BEAN_PREFIX comes to the rescue and it is registered with id &myBean.
From your application you can get access to that bean by id and container returns for you the MyBeanFactoryBean object.
More info you can find from Spring Framework Reference Manual.

How to know if the wiring for a bean is complete with autowiring?

I have a bean with autowired beans.
So something like:
class A
{
#Autowired
B b;
#Autowired
C c;
void function()
{
// here I would like to do something when I an sure the wiring has been done
// being sure that I won't wait forever
...
Something has to exist, but I can't find it.
Thanks for your help!
You can annotate your 'function' method with #PostConstruct and specify <context:annotation-config/> in your spring config XML. Then, function will only be invoked after autowiring, so you could check in function whether your beans have been injected successfully.
A classic way to achieve this is to implement InitializingBean:
Interface to be implemented by beans that need to react once all their properties have been set by a BeanFactory: for example, to perform custom initialization, or merely to check that all mandatory properties have been set.
An alternative to implementing InitializingBean is specifying a custom init-method, for example in an XML bean definition. For a list of all bean lifecycle methods, see the BeanFactory javadocs.
I also suggest reading other answers:
How to call a method after bean initialization is complete?
What is the difference between BeanPostProcessor and init/destroy method in Spring?
If you are using default scope for beans that is singleton, then autowiring will always be done at the application startup only. If wiring for any field fails, then spring container will throw an exception and the application will not start properly. So, if the control of code is in your method , it means wiring has already been done.

Spring AOP - Error Generating proxies

I'm using spring AOP's around advice to capture processing time of a transaction. I'm getting the following error during application startup
error creating bean "coreMessageResourceAccesor"
Could not generate CGLIB subclass of class
[class org.springframework.context.support.MessageSourceAccessor]:
Common causes of this problem include using a final class or a non-visible class;
nested exception is java.lang.IllegalArgumentException:
Superclass has no null constructors but no arguments were given
I identified what the problem is with the help of this thread. But I cannot change coreMessageResourceAccesor bean to use setter based injection because its using a spring class & that class doesn't have no arg constructor
Below is the configuration for the bean
<bean id="coreMessageSourceAccessor"
class="org.springframework.context.support.MessageSourceAccessor" >
<constructor-arg type="org.springframework.context.MessageSource"
ref="coreMessageSource" />
</bean>
I would really appreciate if someone could help. Thanks for your time.
You don't need really need to configure MessageSourceAccessor accessor as a bean, it's generally easier to instantiate it manually as required. So rather than inject the MessageSourceAccessor into your beans, inject the raw MessageSource, and then wrap it in a MessageSourceAccessor as required (i.e. using new MessageSourceAccessor(messageSource)).
You can then put the advice around the MessageSource rather than the MessageSourceAccessor, which will work better. Also, MessageSourceAccessor will not itself add any significant processing time, it's just a thin wrapper around MessageSource.

Why is there a need to specify the class in both the xml file and in the getBean() method in Spring

This might be an obvious but I'm having a hard time understanding why we need to define the class of a bean in two places....
From the spring reference manual...
...
<bean id="petStore"
class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="itemDao" ref="itemDao"/>
<!-- additional collaborators and configuration for this bean go here -->
</bean>
// retrieve configured instance
PetStoreServiceImpl service = context.getBean("petStore", PetStoreServiceImpl.class);
Shouldn't the xml fine be enough for the container to know the class of petStore?
You can use the following method:
context.getBean("petStore")
However, as this returns a java.lang.Object, you'd still need to have a cast:
PetStoreServiceImpl petstore = (PetStoreServiceImpl)context.getBean("petStore");
However, this could lead to problems if your "petStore" bean is not actually a PetStoreServiceImpl, and to avoid casts (which since the advent of Generics are being seen as a bit dirty), you can use the above method to infer the type (and let's spring check whether the bean you're expecting is really of the right class, so hence you've got:
PetStoreServiceImpl service = context.getBean("petStore", PetStoreServiceImpl.class);
Hope that helps.
EDIT:
Personally, I would avoid calling context.getBean() to lookup methods as it goes against the idea of dependency injection. Really, the component that uses the petstore bean should have a property, which can then be injected with the correct component.
private PetStoreService petStoreService;
// setter omitted for brevity
public void someotherMethod() {
// no need for calling getBean()
petStoreService.somePetstoreMethod();
}
Then you can hook up the beans in the application context:
You could also do away with the configuration via XML and use annotation to wire up your beans:
#Autowired
private PetStoreService petStoreService;
As long as you've got
in your spring context, the "petStore" bean defined in your application context will automatically be injected. If you've got more than one bean with the type "PetStoreService", then you'd need to add a qualifier:
#Autowired
#Qualifier("petStore")
private PetStoreService petStoreService;
There's no requirement to specify the class in the getBean() method. It's just a question of safety. Note there's also a getBean() that takes only a class so that you can just look up beans by type instead of needing to know the name.

Autowiring Unmanaged Beans Annotated With #Component

I want to use #AutoWired to inject a non-managed bean configured with #Component into a managed bean. I'm pretty sure I have the configuration right, but for some reason I keep getting the exception:
No unique bean of type [foo.Baz] is defined: Unsatisfied dependency of type [class foo.Baz]: expected at least 1 matching bean
Based on the error, I'm guessing it's not able to find the Baz class, but I'm not sure why. It's my understanding that the context:spring-configured element in the XML config was supposed to allow me to do this. I also made sure to include the appropriate jar files (spring-weaving.jar and aspectjweaver.jar).
Here's a simple example of my set up.
My XML config:
<beans ...>
...
<context:annotation-config/>
<context:spring-configured/>
<context:component-scan base-package="foo"/>
<bean id="bar" class="foo.Bar"/>
...
</beans>
I have one managed bean:
package foo;
public class Bar {
#Autowired
private Baz baz;
public void setBaz(Baz baz) {
this.baz = baz;
}
...
}
And one unmanaged bean:
package foo;
#Component
public class Baz {
...
}
Is there something I'm missing?
EDIT: The log lists the beans its instantiating, and foo.Baz isn't one of them. I don't know why it's not picking up the #Component annotated class.
Because Bar is configured with xml, it can only be configured with xml. i.e. you can't mix them. So that "#Autowired" annotation on Baz is not getting picked up (none of the annotations would be). It is only when you add the spring annotation at class level that spring will listen to any of the other annotations.
What you'll need to do is in the xml configure the bean to be autowired by type, add a setter for that type and you'll achieve the desired behaviour.
<bean id="bar" class="foo.Bar" autowire="byType"/>
One more thing, when you annotate a bean with #Component it is a spring managed bean. Just because it is not created with xml does not mean it is unmanaged. An unmanaged bean is one you don't get from spring.
Bar and Baz are both spring managed. It is the mechanism you've chosen to define them that differs.
The previous response is not correct, in one aspect. You can autowire beans that are otherwise configured with xml.
From section 3.4.5 in http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html:
When using XML-based configuration metadata[2], you specify autowire mode for a bean definition with the autowire attribute of the element. The autowiring functionality has five modes. You specify autowiring per bean and thus can choose which ones to autowire.
You can autowire by name, type and constructor. There is a crude example of this here: http://www.java2s.com/Code/Java/Spring/AutoWiring.htm
The error is due to the sequence of beans defined in your XML config file.
As on your XML file, bean for bar is created first and then their dependent beans due to which #Autowired is not able to find baz.
You must first declare bean for baz and then for bar.

Resources