How Spring AOP works
The following points describe the work of Spring AOP:
- Implement your mainline application logic: Focusing on the core problem means that, when you are writing the application business logic, you don't need to worry about adding additional functionalities, such as logging, security, and transaction, between the business codes-Spring AOP takes care of it.
- Write aspects to implement your cross-cutting concerns: Spring provides many aspects out of the box, which means you can write additional functionalities in the form of the aspect as independent units in Spring AOP. These aspects have additional responsibilities as cross-cutting concerns beyond the application logic codes.
- Weave the aspects into your application: Adding the cross-cutting behaviors to the right places, that is, after writing the aspects for additional responsibilities, you could declaratively inject them into the right places in the application logic codes.
Let's look at an illustration of AOP in Spring:
In the preceding diagram, Spring AOP separates the cross-cutting concerns, for example, security, transaction, and logging, from the business modules, that is, BankService, CustomerService, and ReportingService. These cross-cutting concerns are applied to predefined points (stripes in the preceding diagram) of the business modules at the running time of the application.
Suppose that you want to log the messages before and after calling the transferAmmount() method of TransferService using the services of a LoggingAspect. The following listing shows the LoggingAspect class you might use.
LoggingAspect call is used for logging the system for TransferService:
package com.packt.chapter1.bankapp.aspect; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class LoggingAspect { @Before("execution(* *.transferAmount(..))") public void logBeforeTransfer(){ System.out.println("####LoggingAspect.logBeforeTransfer()
method called before transfer amount####"); } @After("execution(* *.transferAmount(..))") public void logAfterTransfer(){ System.out.println("####LoggingAspect.logAfterTransfer() method
called after transfer amount####"); } }
To turn LoggingAspect into an aspect bean, all you need to do is declare it as one in the Spring configuration file. Also, to make it an aspect, you have to add the @Aspect annotation to this class. Here's the updated AppConfig.java file, revised to declare LoggingAspect as an aspect.
Declaring LoggingAspect as an aspect and enabling the Apsect proxy feature of Spring AOP:
package com.packt.chapter1.bankapp.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import
org.springframework.context.annotation.EnableAspectJAutoProxy; import com.packt.chapter1.bankapp.aspect.LoggingAspect; import com.packt.chapter1.bankapp.repository.AccountRepository; import com.packt.chapter1.bankapp.repository.TransferRepository; import
com.packt.chapter1.bankapp.repository.jdbc.JdbcAccountRepository; import
com.packt.chapter1.bankapp.repository.jdbc.JdbcTransferRepository; import com.packt.chapter1.bankapp.service.TransferService; import com.packt.chapter1.bankapp.service.TransferServiceImpl; @Configuration @EnableAspectJAutoProxy public class AppConfig { @Bean public TransferService transferService(){ return new TransferServiceImpl(accountRepository(),
transferRepository()); } @Bean public AccountRepository accountRepository() { return new JdbcAccountRepository(); } @Bean public TransferRepository transferRepository() { return new JdbcTransferRepository(); } @Bean public LoggingAspect loggingAspect() { return new LoggingAspect(); } }
Here, we're using Spring's AOP configuration based on Java to declare the LoggingAspect bean as an aspect. First, we declare LoggingAspect as a bean. Then we annotate that bean with the @Aspect annotation.
We annotate logBeforeTransfer() of LoggingAspect with the @Before annotation so that this method is called before the transferAmount() is executed. This is called before advice. Then, we annotate another method of LoggingAspect with the @After annotation to declare that the logAfterTransfer() method should be called after transferAmount() has executed. This is known as after advice.
@EnableAspectJAutoProxy is used to enable Spring AOP features in the application. This annotation actually forces you to apply proxy to some of the components that are defined in the spring configuration file. We'll talk more about Spring AOP later, in Chapter 4, Spring Aspect Oriented Programming with Proxy and Decorator Pattern. For now, it's enough to know that you've asked Spring to call logBeforeTransfer() and logAferTransfer() of LoggingAspect before and after the transferAmount() method of the TransferService class. For now, there are two important points to take away from this example:
- LoggingAspect is still a POJO (if you ignore the @Aspect annotation or are using XML-based configuration)--nothing about it indicates that it's to be used as an aspect.
- It is important to remember that LoggingAspect can be applied to TransferService without TransferService needing to explicitly call it. In fact, TransferService remains completely unaware of the existence of LoggingAspect.
Let's move to another way that Spring simplifies Java development.