Transactions, Caching and AOP: understanding proxy usage in Spring

Engineering | Michael Isvy | May 23, 2012 | ...

In the Spring framework, many technical features rely on proxy usage. We are going to go in depth on this topic using three examples: Transactions, Caching and Java Configuration.

All the code samples shown in this blog entry are available on my github account.

Transactions

First step: no transaction

The Service class below is not transactional yet. Let’s first look at it as is and then make it become transactional.

@Service
public class AccountServiceImpl  implements AccountService {
 //…

//Not specifying a transaction policy here!
 public void create(Account account) {
 entityManager.persist(account);
 }
}

Since the method “create” is not transactional, it will most likely throw an exception (because this Account object should not be persisted outside of a transaction).

Here is what we have at runtime: 

Second step: adding transactional behavior configuration

Let us now add @Transactional on top of the create(…) method:

@Service
public class AccountServiceImpl  implements AccountService {
 @PersistenceContext
 private EntityManager entityManager;

 @Transactional
 public void create(Account account) {
 entityManager.persist(account);
 }

}

And here is the corresponding Spring configuration:


<bean id="transactionManager">
 <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<tx:annotation-driven/>

Inside Spring generic configuration, we have used  <tx:annotation-driven /> . It means that all @Transactional annotations should be scanned at startup time and the targeted methods should become transactional. So where is the transactional behavior happening?

Before startup, we still have the same files as before:

At startup time, a new class is created, called proxy. This one is in charge of adding Transactional behavior as follows:

The generated proxy class comes on top of AccountServiceImpl. It adds Transactional behavior to it [1].

So how to make sure that a proxy is indeed being used? For your own understanding, it’s interesting to go back into the code and see with your very eyes that you are indeed using a proxy.

A simple way is to print out the class name:



AccountService accountService = (AccountService) applicationContext.getBean(AccountService.class);
String accountServiceClassName = accountService.getClass().getName();
logger.info(accountServiceClassName);

On my computer, it shows the following output:



INFO : transaction.TransactionProxyTest - $Proxy13

This class is a Dynamic Proxy, generated by Spring using the JDK Reflection API (more information here).

At shutdown (eg. When the application  is stopped), the proxy class will be destroyed and you will only have AccountService and AccountServiceImpl on the file system:

How does Spring wire the proxy in-lieu of the target class?

Let us consider a consider a class that uses an instance of AccountService:
```java

@Controller public class AccountController { private AccountService accountService;

private void setAccountService(AccountService accountService) { this.accountService=accountService; }

//… }



<a href="http://blog.springsource.org/wp-content/uploads/2012/05/proxy-and-target1.png"><img class="aligncenter size-full wp-image-11128" title="proxy-and-target" src="http://blog.springsource.org/wp-content/uploads/2012/05/proxy-and-target1.png" alt="" width="316" height="255" /></a>

</div>
<div>

The attribute accountService is of type AccountService (interface). The variable dependency is on the interface type AccountService, not the implementation type, which reduces the coupling between classes. This is a best practice.

As seen before, both AccountServiceImpl and the generated Proxy implement the interface AccountService.
•    If there is a proxy, Spring injects the proxy
•    If not, Spring injects the instance of type AccountServiceImpl.

</div>
&nbsp;
<h3><a name="cache">Caching</a></h3>
<div>

Declarative caching is a new feature in Spring 3.1 that works like Spring’s declarative transaction support.

The @Cacheable annotation should be used in that way:

</div>
<div>
```java

public class AccountServiceImpl  implements AccountService {

@Cacheable(value="accounts", key="#id")
public Account findAccount (long id) {
 // only enter method body if result is not in the cache already
 }
}

You should also have enabled caching inside Spring configuration as follows:


<cache:annotation-driven />

Here are the expected results:


accountService.findAccount (1); // Result stored into cache for key “1”
accountService.findAccount (1); // Result retrieved from cache. Target method not called.
accountService.findAccount (2); // Result stored into cache for key “2”

At runtime, a proxy is used to add Caching behavior.

Note: Spring 3.1 embeds a fairly simple cache implementation. It is usually recommended to use another implementation such as ehcache. On the sample application available here (https://github.com/michaelisvy/proxy-samples), you’ll find some examples using both the embedded cache implementation and ehcache.

What if the bean class does not implement any interface?

In the previous example, we mentioned that a proxy should implement the same Interface as your bean. Thankfully, Spring can also proxy beans that don’t have an interface. There are many cases where implementing an interface is not the best way to go.

By default, if your bean does not implement an interface, Spring uses technical inheritance: at startup time, a new class is created. It inherits from your bean class and adds behavior in the child methods.

In order to generate such proxies, Spring uses a third party library called cglib. Unfortunately, this project is not active anymore. In Spring 3.2, it is very likely that Spring will be using Javassist instead by default (see here for more details).

Java Configuration

Note: this section requires some background knowledge of Java Configuration in Spring. Please feel free to skip it if you are not comfortable with this new configuration style.

You can learn more about Java Configuration here.  There is also an excellent article which discusses the various configuration styles here.

When using Java Configuration, the configuration is stored in a Java class such as this one:
```java

@Configuration public class JavaConfig {

@Bean public AccountService accountService() {

return new AccountServiceImpl((accountRepository()); } @Bean public AccountRepository accountRepository () { //… }

}



Spring calls the method accountService() every time it needs to wire an instance of the bean “accountService” and this one returns a “new” object of type AccountService. If 10 beans are using a dependency of type AccountService, this method is called 10 times.

However, no matters the Spring configuration has been made using Java Configuration or not, every bean should be a singleton by default. How is that possible and where is the magic happening?
This diagram explains how things work internally:

</div>
<div><a href="http://blog.springsource.org/wp-content/uploads/2012/05/java-config.png"><img class="aligncenter size-full wp-image-11131" title="java-config" src="http://blog.springsource.org/wp-content/uploads/2012/05/java-config.png" alt="" width="507" height="328" /></a></div>
<div>

So the Proxy is adding behavior there. In the case that your bean should be a singleton, the action to turn your Plain Old Java Object into a singleton is performed by a child class (Proxy).

</div>
<div>
&nbsp;
<h3>Conclusion</h3>
We’ve seen some use-cases on how proxies are used inside the Spring framework. There are many other examples: Aspect Oriented Programming, Security (using Spring Security), thread safety, scopes, etc…

If you would like to know more on the impact on performance when using proxies, you can read <a href="http://blog.springsource.org/2007/07/19/debunking-myths-proxies-impact-performance/">Alef Arendsen’s blog entry here</a>.

</div>
<div>

<hr size="1" />

<div><a name="note">[1]</a>to be exact: the proxy class does not contain the transaction code internally. It delegates transaction handling to some classes that are part of the Spring framework. Spring will then handle transactions according to the Transaction Manager you have declared.&nbsp;

</div>
</div>

Get the Spring newsletter

Thank you for your interest. Someone will get back to you shortly.

Get ahead

VMware offers training and certification to turbo-charge your progress.

Learn more

Get support

Tanzu Spring Runtime offers support and binaries for OpenJDK™, Spring, and Apache Tomcat® in one simple subscription.

Learn more

Upcoming events

Check out all the upcoming events in the Spring community.

View all