How #Aspect with #Component annotation works under the hood - spring

I've been looking for an answer for a while, but no luck so far, thus I'm coming here for some words of wisdom.
I've created an aspect using #Aspect annotation, because I need to #Autowire some singleton dependencies I've decided to annotate this aspect class with #Component and let the Spring to do the magic. It works, however ...
I'm fairly familiar with AOP concept, what's weaving and different flavors of it (cglib vs aspectj) but it's not fully intuitive to me how it works under the hood.
#Component means a given class will be a singleton within a given context, #Aspect means that the content of an aspect class will be somehow weaved into the target class during runtime/compilation - and this target class is not a singleton but prototype for instance. So what I'm ending up with at the end?

Spring AOP does not do compile-time-weaving and does not modify the code of the advised target. Instead it works with proxies that are weaved around the joinpoints. That is why Spring AOP aspects and be used as (singleton) components, have their fields autowired, etc., like any other Spring Proxy.
It is also the reason why Spring AOP aspects only work for public method executions, not field accesses and the like.
The documentation is quite well written and goes into as much (or as little) detail as one might like:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html

The book AspectJ in Action's section 2.5 is on the internal working of the weaving step, it is only 2 page but gets the point across well.
Luckily the section is available here.
This is for posterity.

Related

Spring Context Test With Just One Bean

What's the recommended way to run a spring boot test where only the one subject under test is configured in the context.
If I annotate the test with
#RunWith(SpringRunner.class)
#SpringBootTest(properties = "spring.profiles.active=test")
#ContextConfiguration(classes = MyTestBean.class)
Then it seems to work - the test passes, the context starts quickly and seems to only contain the bean that I want. However, this seems like an incorrect use of the #ContextConfiguration(classes = MyTestBean.class) annotation. If I understand correctly the class that I reference is supposed to be a Configuration class, not a regular spring service bean or component for example.
Is that right? Or is this indeed a valid way to achieve this goal? I know there are more complex examples like org.springframework.boot.test.autoconfigure.json.JsonTest which use #TypeExcludeFilters(JsonExcludeFilter.class) to control the context - but this seems overkill for my use case. I just want a context with my one bean.
Clarification
I know that I can just construct the one bean I am testing as a POJO without a spring context test and remove the three annotations above. But in my precise use case I am actually reliant on some of the configuration applied to the context by settings in the application-test.properties file - which is why I've made this a Spring Boot test with a profile set. From my perspective this isn't a plain unit test of a single class in isolation of the spring context configuration - the test is reliant on certain configuration being applied (which is currently provided by the spring boot app properties). I can indeed just test the components as a POJO by creating a new instance outside of a spring context, I'm using constructor injection making the providing of necessary dependencies simple but the test does rely on things like the log level (the test actually makes assertions on certain logs being produced) which requires that the log level is set correctly (which is currently being done via logging.level.com.example=DEBUG in a properties file which sets up the spring context).
For starters, reading the documentation first (e.g., the JavaDoc linked below in this answer) is a recommend best practice since it already answers your question.
If I understand correctly the class that I reference is supposed to be
a Configuration class, not a regular spring service bean or
component for example.
Is that right?
No, that's not completely correct.
Classes provided to #ContextConfiguration are typically #Configuration classes, but that is not required.
Here is an excerpt from the JavaDoc for #ContextConfiguration:
Annotated Classes
The term annotated class can refer to any of the following.
A class annotated with #Configuration
A component (i.e., a class annotated with #Component, #Service, #Repository, etc.)
A JSR-330 compliant class that is annotated with javax.inject annotations
Any other class that contains #Bean-methods
Thus you can pass any "annotated class" to #ContextConfiguration.
Or is this indeed a valid way to achieve this goal?
It is in fact a valid way to achieve that goal; however, it is also a bit unusual to load an ApplicationContext that contains a single user bean.
Regards,
Sam (author of the Spring TestContext Framework)
It is definitely a reasonable and normal thing to only test a single class in a unit test.
There is no problem including just one single bean in your test context. Really, a #Configuration is (typically) just a collection of beans. You could hypothetically create a #Configuration class just with MyTestBean, but that would really be unnecessary, as you can accomplish doing the same thing listing your contextual beans with #ContextConfiguration#classes.
However, I do want to point out that for only testing a single bean in a true unit test, best practice ideally leans towards setting up the bean via the constructor and testing the class that way. This is a key reason why the Spring guys recommend using constructor vs. property injection. See the section entitled Constructor-based or setter-based DI of this article, Oliver Gierke's comment (i.e. head of Spring Data project), and google for more information. This is probably the reason you're getting a weird feeling about setting up the context for the one bean!
You can also use ApplicationContextRunner to create your context using a test configuration of your choice (even with one bean if you like, but as other people have already mentioned for one bean it's more reasonable to use the constructor the classical way without using any spring magic).
What I like this way of testing is the fact that test run very fast since you don't load all the context. This method is best used when the tested bean doesn't have any Autowired dependencies otherwise it's more convenient to use #SpringBootTest.
Below is an example that illustrates the way you can use it to achieve your goal:
class MyTest {
#Test
void test_configuration_should_contains_my_bean() {
new ApplicationContextRunner()
.withUserConfiguration(TestConfiguration.class)
.run(context -> {
assertThat(context.getBean(MyTestBean.class)).isNotNull();
});
}
#Configuraiton
public static class TestConfiguration {
#Bean
public MyTestBean myTestBean(){
new MyTestBean();
}
}
}

Implementing an interface is tight coupling?

It says here that
I would not recommend to use InitializingBean and DisposableBean
interface, because it will tight coupled your code to Spring
Does it make sense? I thought this would be just the opposite to tight-coupling.
Here the author means that if you let your application classes implement InitializingBean and DisposableBean interfaces (that are spring specific interfaces), then you are coupling your code with spring.
In future if spring renames these interfaces (unlikely though), or you stop using spring you will have to update your class code.
Instead if you use init-method and destroy-method attributes in your bean config, your class is independent of spring, i.e. there is no depedency of your class on spring specific classes.
Hope it helps.
I think the idea here is to not create any dependency on your code to spring annotations, see
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
When you explicitly declare this kind of dependency, you're coupling your code to spring jars.
In this other example - http://www.mkyong.com/spring/spring-init-method-and-destroy-method-example/ - it shows how you could use convention methods defined in the XML. No spring imports.

Best Practise of injecting applicationContext in Spring3

As in the title above, I am confused about pros cons between injecting applicationContext by directly #Autowired annnotation or implementing ApplicationContextAware interface in a singleton spring bean.
Which one do you prefer in which cases and why? Thanks.
Actually, both are bad. Both of them tie your application to the Spring framework, thus inverting the whole inversion-of-control concept. In an ideal world, your application should not be aware of being managed by an ApplicationContext at all.
Once you have chosen to violate this principle, it doesn't really matter how you do it. ApplicationContextAware is the legacy version that has been around at least since Version 2.0. #Autowired is a newer mechanism but they work in pretty much the same way. I'd probably go with ApplicationContextAware, because it semantically makes clear what it is about.
As #Sean Patrick Floyd says, the need of ApplicationContext is often due to a bad design. But sometimes you have no other option. In those cases I prefer the use of #Autowired because is the way I inject all other properties. So, if I use #Autowired for injecting MyRepository, why can't I use it for ApplicationContext or any other Spring bean?
I use Spring interfaces only for those things I can't do with annotations, for example BeanNameAware.
If you need to get a prototype in a singleton then you can use method injection. Basically, you create an abstract method that returns the object you need and spring will return the prototype everytime you call that method. You define the "lookup-method" in your spring config. Here are some links:
http://docs.spring.io/spring/docs/1.2.9/reference/beans.html#beans-factory-method-injection
http://java.dzone.com/articles/method-injection-spring
Since you are not extending any of the spring classes your application is always separated from the framework. Most of the cases you will not wanted to inject the ApplicationContext as it, but will need to inject the beans defined in the ApplicationContext.
The best case is always to stick to the bare minimum, until and unless you have any specific requirement and this is very simple with spring.
So either,
Annotate your beans and scan them in application context, then use #Autowire to wire them up.
Use application context to wire your bean expediencies(old xml style configs). You can use #Autowire with this approach also.
When you want to control the bean life cycle, you can read the API and customize it, but most of the time these general settings will do the job.
Here are some examples.
Spring Auto-Wiring Beans with #Autowired annotation
Spring Auto-Wiring Beans XML Style
Spring IoC container API Docs
There is no need to use ApplicationContext at all.
ObjectFactory
If you need to use prototype scoped beans in a singleton bean, inject an org.springframework.beans.factory.ObjectFactory.
For example using constructor injection:
#Service
class MyClass {
private ObjectFactory<MyDependency> myDependencyFactory;
public MyClass(ObjectFactory<MyDependency> prototypeFactory) {
myDependencyFactory = prototypeFactory;
}
}
Why
Now what's the benefit over using ApplicationContext ?
You can substitute this dependency (e.g. in a test) by simply passing a lambda (since ObjectFactory is a #FunctionalInterface) that returns a stubbed version of it.
While it is possible to stub the ApplicationContext, it is not clear in that case which beans will be looked up and need to be stubbed.

Spring AOP: Disadvantages when using it - Spring Features which use Spring AOP do not have this disadvantages?

Im working with the Spring Framework 3.0.5 and Spring Security 3.0.5 and Ive got questions to the aspect orientated programming. At the moment Im trying to figure out the disadvantages and advantages of aspect orientated programming. Of course, I know them in theory: I can avoid redundant code, I only have to make changes in the aspect, not everywhere in the code and so on. But I still got some questions:
The disadvantage I found out:
I wrote a sample application using aspects with Spring AOP. I configured an Aspect with Annotations (#Pointcut, #Before, #Aspect and so one). The methods that triggered the aspect (which were part of a Pointcut of course) were of course part of a different class and not annotated with anything.
=> I really think that one big disadvantage is that when watching those methods of the other class it was not clear that they trigger an aspect. They needed no annotations or anything else, they were just mentioned in the pointcut of the aspect. (I really hope you understand what I mean). So thats why I think that AOP makes code also less understandable!
a) Is there a solution to this problem? (Can this maybe be solved when I put the whole configuration in an XML File? I dont think so.)
b) Would this problem still exist when I would use AspectJ instead of Spring AOP?
Springs Features using Spring AOP: they dont have this disadvantage?
As Spring AOP is part of many Spring Features (just like declarative Transaction Management or (maybe) Spring Security(?)) I took a closer look at those Features. I was not able to find any disadvantage at all.
c) Lets take the declarative transaction management as an example: managing transactions is so easy with those annotations (#transactional) and I dont really find the disadvantage I mentioned above. I can see the methods that trigger specific behaviour. (all #transactional methods trigger transactional behaviour) Maybe I misunderstood something and this isnt where AOP is used? But if I did not misunderstood this, why is it here possible to see which methods trigger aspects and why isnt it possible to see in my example above? I would really like to know this!
Thank you for answering! :-)
EDIT: a) and b) are answered (use an IDE which marks those methods), c) is still missing :-)
For Point b)
If you use an Eclipse with Spring IDE and AspectJ plugin, or STS, the IDE will show you where Aspects are woven in.
For Point b)
If you use AspectJ and an IDE that supports AspectJ (Eclipse with AspectJ Plugin, or STS), then you will see markers in the souce-code where the Aspect is woven in.
An disadvantaged of Compile time AspectJ is, that you are not able to wove aspects in libraries. (without advanced techniques).
For Point c)
There is only one disadvantage of declarative Aspects like #Transactional. -- You can forget to put the annotation on the method.
But if you have for example a rule like: every public method in a Class annoteted by #Service (or if you like to build you own #TransactionalService), is transactional, then you do not need to specifiy the #Transactional annotation on each method. -- So in Summary: declarative Aspects are very good for reading (you will not overlook them), and they are good if your code is very (lets say) "individual" (instead of the term "not consistent") . But If you work in an Environment with Strong Architecural Rules (like every public method in a #Service class...), then you can Write this rules down in a Point Cut Definition, instead of using declarative Aspects.
Actually for point a) the same answer holds that Ralph gave: use Eclipse with either AspectJ plugin or if you are using Spring anyway, use STS.
That way you will see in your IDE if a certain method matches a pointcut on the left side of your editor, represented by small red arrows:
Actually, Spring AOP supports creating custom annotations.
I defined a annotation named Loggable binding with Advice.The Loggabel could be applied to any method you want.
public #interface Loggable {
}
#Aspect
public class EmployeeAnnotationAspect {
#Before("#annotation(com.ben.seal.spring.aspect.Loggable)")
public void myAdvice(){
System.out.println("Executing myAdvice!!");
}
}

Managing complexity in a dependency-injected app with a large number of beans

I'm working on an Spring application which has a large number of beans - in the hundreds - and it's getting quite cumbersome to use and document.
I'm interested in any experience you have with DI-enabled apps with a large number of beans which would aid maintainability, documentation and general usage.
Although the application is Spring-based with a couple of context files, I'm open to listening about suggestions regarding any DI container and about DI in general as well.
You can use component scan and autowiring features to dramatically decrease the amount of Spring XML configuration.
Example:
<beans>
<!-- Scans service package looking for #Service annotated beans -->
<context:component-scan base-package="my.root.package.service"/>
</beans>
Your service classes must be annotated in order to be automatically scanned:
package my.root.package.service;
#Service("fooService")
public class FooServiceImpl implements FooService{
}
You can also use the #Autowired annotation to tell Spring how to inject the bean dependencies:
package my.root.package.service;
#Service("barService")
public class BarServiceImpl implements BarService{
//Foo service injected by Spring
#Autowired
private FooService fooService;
//...
}
I found the following to be of use:
split your Spring configurations into multiple standalone configurations, and use Spring's import facility to import configuration dependencies (see here, section 3.2.2.1). That way you have a set of configurations that you can combine or disassemble as required, and they are all self-dependent (all the dependencies will be explicit and referenced)
Use an IDE that is Spring-aware, and allows you to navigate through the configurations via point-n-click on beans (references/names, to-and-from source code). Intellij works very well at this (version 7 and beyond, I think). I suspect Eclipse would do something similar.
Revise what you're injecting where. You may want to refactor multiple bean injections into one composite or 'meta' bean, or a larger component. Or you may find that components you once thought you'd need to inject have never changed, or never demanded that injectability (for testing, implementing as strategies etc.)
I used to work with a huge Spring installation, with hundreds (thousands?) of beans. Splitting the configurations up made life a lot more manageable, and simplified testing/creating standalone processes etc. But I think the Intellij Spring integration that came with Intellij made the most difference. Having a Spring-aware IDE is a major timesaver.
As #Wilson Freitas says, use autowiring. I daily work with a system that has few thousand spring managed beans using mostly autowired. But I think the notion of "retaining the overall picture" is slightly misplaced. As a system grows you can't expect to do that in the same way as you did on a smaller system. Using #Autowiring forces you to use stronger typing than xml-based spring, which again means you can use the dependency tracking features of your IDE to navigate in dependencies.
I really think it's suboptimal to think that you need to understand too much of the "full" picture when it comes to the spring configuration. You should be focusing on your code and it's dependencies. Managebility and maintainability are achieved by organizing this code well, naming things well and managing your coupling; all of the stuff that applies even if you're not using spring. Spring shouldn't change much, and with the approval of JSR-330, it may even seem like dependency injection will creep further "under the hood" of the runtime environment.
Our strategy is:
naming conventions, e.g.: fooService, fooDao, fooController;
property setters following these conventions;
autowiring by name (autowire="byName"); we had many problems with autowiring by type, especially on the controller layer

Resources