I have an aspect which creates by load-time weaving mechanism. But I need to inject my service in it, so it aspect must be created by spring.
My aspect looks like this :
#Aspect
public class SomeAspect {
#Inject
private SomeService someService;
#Before("some_pointcut_here")
public void doInterception() {
//...call service here
}
}
I can do it with xml:
<bean id="myAspect" class="foo.bar.SomeAspect" factory-method="aspectOf" />
So the question is how to achieve the same with spring java config. Any suggestions will be appreciated. Thanks
Edit
I annotate my aspect with #Component and it works. It strange for me because in case of xml config dependency injection doesn't worked in my case, but it works for java configuration
#Bean
public SomeAspect someAspect() {
return org.aspectj.lang.Aspects.aspectOf(SomeAspect.class);
}
Related
What is the programatic equivalane to defining a bean like this in xml:
<bean id="foo" class="com.bizz.Foo" />
Ideally I would like to be able to have spring create that bean, without using XML and without calling new and for this to happen within a #Configuration type class. For example:
#Configuration
public ConfigBar {
#Bean
public com.bizz.Foo foo() {
return /* Programmatic equivalent of <bean id="foo" class="com.bizz.Foo" /> here*/;
}
}
I don't think new Foo() is equivalent:
as spring is able to pick which constructor to use which may not be the no args constructor.
and spring is able to inject dependencies, which I don't think will be done here.
I know that spring is doing some reflection to achieve this, however simply stating that is not the answer to this question.
so how can we let spring create the Foo bean programmatically letting spring inject dependencies, pick the constructor and perhaps other tasks that spring would normally do when defined in XML?
The equivalent is #Component or any variant thereof such as #Controller or #Service. So long as your bean is in a package included in the component scan Spring will be able to find your bean at runtime and inject it into other beans.
As an example:
#Component
public class Foo {
//...
}
#Service
public class Bar {
// Spring will find and inject Foo bean creating it if necessary when
// creating the Bar "service" bean
#Autowired
private Foo foo;
//...
}
I have worked it out:
#Bean
#Autowired
public Foo foo(AutowireCapableBeanFactory autowireCapableBeanFactory) {
return autowireCapableBeanFactory.createBean(Foo.class);
}
I am working on some legacy code that uses spring bean definitions on xml.
The module I am building uses annotations.
The problem is that sometimes I need to override a legacy bean definition so I need to put my beans on xml as well.
I have the following:
public class BeanIAmOverriding {
private MyAnnotatedBean bean;
}
#Component
public class MyAnnotatedBean {
private Repository repo;
}
#Repository
public class Repository {
#Transational
public Something find(...)
}
Xml file:
<bean id="bean" class="a.b.c.BeanIAmOverriding"/>
In this scenario, my repository does NOT get proxied with the transactional aspec.
I even tried just aliasing it but the same thing happens.
My current workaround is implementind BeanFactoryAware.
Do you have any better ideas?
EDIT:
Let me clarify.
I do know dependency injection, I just ommited some configuration I didn't think would be that relevant given the context, but here they are.
I would like to do something like:
<bean id="bean" class="a.b.c.BeanIAmOverriding">
<constructor-arg index="0" ref="myAnnotatedBean"/>
</bean>
That doesn't work. When I do that my Repository does not get proxied by the transactional aspect.
So I have this workaround:
public class BeanIAmOverriding implements BeanFactoryAware{
//private MyAnnotatedBean bean;
private BeanFactory beanFactory;
public void something(){
beanFactory.getBean(MyAnnotatedBean.class).doSomething();
}
#Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}
Like I said in my comment, the problem is that you're not injecting the 'BeanIAmOverriding.bean', as spring doesn't know it has to inject it! Try the following (I'm not 100% sure if the following will work, as it's been a long time since I worked on a project that used a mix of 'legacy' xml and annotations).
public class BeanIAmOverriding {
private MyAnnotatedBean bean;
#Autowired
public BeanIAmOverriding(MyAnnotatedBean bean) {
this.bean = bean;
}
}
The #Autowired annotation will tell spring how to instantiate the class. Spring will then take the instance of MyAnnotatedBean and inject it in the constructor.
I'm not sure how experienced you are with Spring, but I would recommend you to read a bit the section on dependency injection.
ISSUE:
I am trying to inject a service into a bean but the service instance is always null.
BACKGROUND:
I have two beans one called from the other. This is how they are defined in XML config:
<context:annotation-config />
<bean class="com.test.MyBeanImpl" name="myBean"/>
<bean id="myService" class="com.test.MyServiceImpl" />
and the beans are implemented like so:
MyServiceImpl.java
class MyServiceImpl implements MyService {
public void getString() {
return "Hello World";
}
}
MyBeanImpl.java
#Component
class MyBeanImpl implements MyBean, SomeOtherBean1, SomeOtherBean2 {
#Resource(name="myBean")
private MyService myService;
public MyBeanImpl() {}
}
QUESTIONS:
Is there some reason related to the fact that my bean implements 3 interfaces that is preventing the Service being injected? If not what other factors could be effecting it?
as you are using annotations Just mark your service class with #Service annotation and use #Autowired annotation to get the instance of your service class
MyServiceImpl.java
package com.mypackage.service;
#Service
class MyServiceImpl implements MyService {
public void getString() {
return "Hello World";
}
}
MyBeanImpl.java
#Component
class MyBeanImpl implements MyBean, SomeOtherBean1, SomeOtherBean2 {
#Autowired
private MyService myService;
public MyBeanImpl() {}
}
also make sure you mention your package name in <context:component-scan /> element in your dispatcher file as
<context:annotation-config />
<context:component-scan base-package="com.mypackage" />
hope this will solve your problem
Make sure the bean you are injecting MyService into is a bean.
/* This must be a bean, either use #Component or place in configuration file */
#Component
public class SomeClass{
#Resource
private MyService myService;
}
Also make sure that within your configuration you have specified that the application uses annotation-based configuration using:
<context:annotation-config/>
Since your using multiple interfaces it may be best to qualify the bean with a name:
<bean class="com.test.MyBeanImpl" name="myBean" />
Then specify the name element on the #Resource annotation
#Resource(name="myBean")
private MyService myService;
Here is a Github Gist that explains these concepts.
I am trying to autowire a class into a WebSocketServlet in the following way:
#Configurable(autowire=Autowire.BY_TYPE)
public class MyServlet extends WebSocketServlet {
#Autowired
public MyClass field;
// etc...
}
Here's what my configuration looks like:
<context:annotation-config />
<context:component-scan base-package="org.*" />
<bean id="config" class="org.*.MyClass">
<!-- a bunch of properties -->
</bean>
Note that autowire used to work just fine as long as I was in a Spring #Controller. I had to step out of that because i don't know how to map a WebSocketsServlet to a method of the #Controller as you do with regular servlets.
Any idea what I might be missing?
In order to use #Configurable, you need to have these line in tour context:
<context:load-time-weaver aspectj-weaving="true"/>
<context:spring-configured/>
<context:annotation-config />
<context:component-scan base-package="org.*" />
In addition, I think you must reference spring-aspect in the Import-Library section of your Manifest.
I didn't succeed to make it work, there is a post on this in the Virgo forum at Eclipse.
If you succeed, let me know how ;)
Getting rid of #Configurable and doing the following in the servlet init method does the trick:
#Override
public void init() throws ServletException {
super.init();
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
As per the spring documentation
Externalized values may be looked up by injecting the Spring Environment into a #Configuration class using the #Autowired or the #Inject annotation:
#Configuration
public class AppConfig {
#Inject Environment env;
#Bean
public MyBean myBean() {
MyBean myBean = new MyBean();
myBean.setName(env.getProperty("bean.name"));
return myBean;
}
}
Is it possible to convert the following XML configuration to an annotation based one?
<bean id="myBean" class="my.package.MyBeanClass" scope="prototype" />
I'm using Spring 2.5.6.
You can use the #Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) annotation.
#Service
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class CustomerService {
// ...
}
Spring API Docs.
Example of the mapping.
Scope annotation reference.
As of the current spring version 4.3.2, we can use #Scope("prototype") annotation.
#Scope("prototype")
#Repository
public class MovieFinderImpl implements MovieFinder {
// ...
}
In Spring 5, You can use as follows
#Component("myBean")
#Scope("prototype")
public class MyBeanClass{//your logics}