Enable Spring AOP or AspectJ - java

This is following on from this question:
Spring autowired bean for #Aspect aspect is null
My initial understanding was that when using Spring AOP, classes annotated with #Aspect are created as spring managed beans, so dependency injection would work as normal. However it seems that an object with the #Aspect annotation is created as a singleton outside the spring container, hence me having to configure it in XML like so in order to enable it as a spring managed bean:
<bean id="aspect" class="com.mysite.aspect" factory-method="aspectOf" />
This has now completely confused me. I thought the following configuration would use spring AOP:
<context:component-scan base-package="com.mysite.aspectPackage"/>
<aop:aspectj-autoproxy/>
So it would scan for #Aspect annotations using component-scan creating aspect beans, and then autoproxy would create a beanPostProcessor which proxies all beans within my context with the appropriate advice. I then thought to enable aspectJ I would need a completely different XML configuration (which incidentally I can't seem to find an example of in the documentation). It would be this configuration that uses aspectJ to create aspects that would be outside of my container or which work by manipulating bytecode rather than proxying.
Note
This is not a question on the difference between spring AOP and aspect J, this is well articulated here:
Spring AOP vs AspectJ

#Aspect is not a spring annotation, and it is not detected by component-scan. So you have to register it somehow as a spring bean. The aspectOf solution works. You can also try
#Aspect
#Component

#Component will create 2 instances, one inside the Spring container, one inside the aspectJ container.
use #Configurable to allow spring to manage dependency injection etc. for your class when instantiated by the aspectj container.
#Aspect is an aspectj style annotation that is supported by spring-aop, where runtime weaving is used to handle interception etc.
Compile-time weaving allows you to disregard the use of as pointcuts will be present in the bytecode, this is done via the aspectj compiler (See https://www.mojohaus.org/aspectj-maven-plugin/ for mvn integration) .
Whether you use the aspectj compiler or spring-aop makes no difference, it wont create your aspect as a managed bean in the way you want unless you use factory / configurable.
Aspectj configuration is, strictly, the pointcut definitions etc that will be present inside your class.

Related

Why you have to anotate classes in Spring boot with service etc.?

Everyone says that it's because spring boot in that case will know that service exists. But if you call that service's method in another method that you try to run when the web app is running. Should it know the service exists without the annotation or not?
The main reason you put these stereotype annotations to classes is creating beans in application context and let the IOC container to provide the management and configuration of these beans depending on their stereotypes.
Spring is an IOC container responsible for instantiating, configuring and assembling these beans. And putting stereotype annotation is just a way to define bean.
You can define beans in various ways such as using #Bean annotation, stereotype annotations, XML definitions etc. and if you don't define your bean, the IOC container can not detect and instantiate the service.

How to inject application context into AspectJ aspects?

How can I inject beans into a real AspectJ aspect using an annotation based application context?
I've created an aspect with AspectJ that implements ApplicationContextAware to access spring beans. Whenever the new-operator of a specified class is invoked, the aspect should inject a spring bean into the newly created instance.
To inject the application context into the aspect, Spring needs a handle to this aspect. The aspect itself is not created by spring but by the AspectJ runtime.
In an xml based application context one can achieve this by
<bean class="SomeAspectClass"
factory-method="aspectOf">
</bean>
But how can I do this in an annotation based context?
My current workaround is to provide an xml based context that contains just this bean definition and merge it into my annotation based application context. But I just want to solve this with my annotation based context.
As avery aspect has a static method 'aspectOf' to access its unique instance, just use reflection to invoke 'aspectOf' and get this instance.

Spring support for #Controller given by <context:component-scan /> vs <mvc:annotation-driven>

I've been researching what additional capabilities we have when using the mvc:annotation-driven tag and I'm having a difficult time digesting the results, especially in regards to the #Controller annotation. I know this is very similar to this question but please hear me out.
According to the Spring docs
The basic purpose of the #Controller annotation is to act as a stereotype for the annotated class, indicating its role. The dispatcher will scan such annotated classes for mapped methods, detecting #RequestMapping annotations (see the next section).
The documentation then goes on to show that the context:component-scan tag provides this support. So that's all well and good, but then I was looking at what mvc:annotation-driven gives us, and the aforementioned stackoverflow question provides the following answer
mvc:annotation-driven declares explicit support for annotation-driven MVC controllers (i.e. #RequestMapping, #Controller, although support for those is the default behaviour), as well as adding support for declrative validation via #Valid and message body marshalling with #RequestBody/ResponseBody.
This seems kind of redundant to me. Maybe I don't get what this explicit support is. Again, referring back to the official Spring documentation we get the following
[mvc:annotation-driven] registers the DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter beans that are required for Spring MVC to dispatch requests to #Controllers.
That sounds pretty similar to the last example I provided from the docs. If anyone can provide some examples as to what we can do with the #Controller annotation using only the context:component-scan tag, what some of the limitations are, then the additional functionality of what we get when adding the mvc:annotation-driven tag, I think that would be very helpful. Thanks in advance for any support on this.
Both elements serve an entirely different purpose.
<context:component-scan /> is, as the name implies, for component scanning. It by default scans for all beans with the #Component annotation (or "sub"annotations like #Controller, #Service etc.). It will only register instances of those classes in the application context as beans. That is all.
<mvc:annotation-driven /> is for bootstrapping Spring MVC and it registers, amongst others, a RequestMappingHandlerMapping and RequestMappingHandlerAdapter. The first links requests to a certain method (the #RequestMapping annotation on methods in a #Controller annotated class). The last knows how to execute methods annotated with #RequestMaping.
Now <mvc:annotation-driven /> does nothing for scanning or detecting #Controllers if there are none in the application context then no request mappings are made. Now you have several ways of registering those beans in the application context and one of them is the aforementioned <context:component-scan />.
Basically a #Controller without <mvc:annotation-driven /> is, well, pretty useless as it does nothing but take up memory. It will not be bound to incoming requests, it just hangs around in the application context. It is just another bean like all other beans and nothing special is being done to it. (Recent, but deprecated, versions of Spring register the DefaultAnnotationHandlerMapping which processes the #Controller, this is however deprecated).
The context:component-scan element lists a package that Spring should scan for #Controller annotations (in the base-package attribute).
the mvc:annotation-driven has no such attribute. This is a convenience element that installs a lot of default MVC elements into the application context. These elements are listed in section 16.14.1 of the Spring framework reference. This element does not appear to scan for #Controller annotations.
Contrary to popular belief, there is no dependancy between these elements. An #Controller without mvc:annotation-driven will function without an issue and handle HTTP requests just fine, as long as you have included context:component-scan with an appropriate base-package attribute.
Case 1(annotation-driven)
This is Enabling Spring annotations tag.
All the annotations such as #Controller, #Service, #Autowired etc.. can be used.
This doesn't creates a bean, but find the the annotations, and spring creates corresponding bean for that class if found annotation(such as #Controller, #Service, #Autowired etc..) .
Case 2(component-scan)
Spring will scan the package (and subpackages) of the classes specified in declaration and creates bean for it.

Inject Spring beans into RestEasy

Is it possible to inject Spring beans into an RestEasy #Path class? I managed to do it with Jersey, with #InjectParam annotation, but for some other reasons, I need to switch to RestEasy, and I can't seem to find a way to do it (tried good ol' javax.inject.Inject, but nothing).
EDIT
This solution works:
http://www.mkyong.com/webservices/jax-rs/resteasy-spring-integration-example/
but it's not injection.. I'd still prefer something a little more elegant.
Simply annotate your RestEasy class with Spring's #Component and then inject your beans using Spring's #Autowired. Don't forget to include the annotation-config and component-scan elements in your spring configuration.
There is a working example that integrates RestEasy with Spring just try spring-resteasy.
You could use the #Configurable annotation to make a normal class (created by new) a spring Bean.
Then you can use the normal Spring annotation to inject everything in that class/instance like in a "normal" Spring Bean.
But that requires AspectJ!
#See Spring Reference Chapter 7.8.1 Using AspectJ to dependency inject domain objects with Spring
I totally agree with Peter's answer but there is another way to do it: you make all your exposition beans (RESTEasy or JAX-WS, which are not Spring components) extending the SpringBeanAutowiringSupport.
That way you can easily inject your Spring Services by #Autowired annotation in these classes.

Something like EJB wiring in Spring for non EJB's

I've noticed recently that spring can wire up my ejb's for me if I annotate the ejb with #Interceptors(SpringBeanAutowiringInterceptor.class). I've never actually done this so don't know the details.
I was wondering, is there a way to get this to work with other kinds of beans, for example, #WebService annotated ones as well.
At the moment in my web service classes (because the application server manages them) I have to load the dependencies from the BeanFactory and would thus prefer to have them autowired.
I know I could use the #Configurable annotation but am not particularly keen to have to specify and agent on the VM.
Is this possible?
Once again, spring has thought of this use case and catered for it!
The problem is that #WebService is not a spring annotation, it is a JAX-WS annotation and thus classes that are annotated with #WebService to be exposed as web services are not managed by spring, but their life cycle is managed by JAX-WS.
The way to handle this case is to have the JAX-WS managed bean extend org.springframework.web.context.support.SpringBeanAutowiringSupport - this will enable the #Autowire annotation, for example, to work in this bean. see here for more information
Yes, of course. There's #WebService, #Repository, #Controller, #Service, #Endpoint, and other annotations in Spring. Here's an example.

Categories