Autoproxy in Spring Aspect-Oriented Programming (AOP)

Exclusive offer: get 80% off this eBook here
Spring 2.5 Aspect Oriented Programming

Spring 2.5 Aspect Oriented Programming — Save 80%

Create dynamic, feature-rich, and robust enterprise applications using the Spring framework

₨587.06    ₨117.41
by Massimiliano Dessì | February 2009 | Java Open Source Web Development

Spring allows us to use "autoproxy" bean definitions, which can automatically proxy selected bean definitions. There are three kind of autoproxies provided for automatic creation of beans. In this article by Massimiliano Dessi, we will look at this in detail.

Autoproxy with classic Spring

By using the class ProxyFactoryBean, AOP can be used in a classic way. But writing separately for each bean on which we want to apply an advisor is not a pleasant thing to see, especially if they are many. So let's consider it as a practicable way only if the beans to be configured in that modality are few.

On the other hand, if the beans to which we have to apply AOP are many, in order to avoid finding ourselves with very long configuration files, we adopt another tactic: We use the auto proxy creator's system, which allows us to automatically create proxies for the beans and prevent using ProxyFactoryBean.

There are two classes made available by Spring to allow the auto proxy creator: BeanNameAutoProxyCreator and DefaultAdvisorAutoProxyCreator.

BeanNameAutoProxyCreator

BeanNameAutoProxyCreator just has a list of beans names to which proxy can be created automatically.

The way in which the autoproxy is created is really simple. It implements the BeanPostProcessor interface, which in its implementation replaces the bean (target) with a proxy.

Example:

This is the interface describing an animal.

package org.springaop.chapter.three.autoproxy.domain;

public interface Animal {

public Integer getNumberPaws();
public Boolean hasTail();
public boolean hasFur();
public Boolean hasHotBlood();

}

The (interface) Bird extends Animal.

package org.springaop.chapter.three.autoproxy.domain;

public interface Bird extends Animal{

public Boolean hasBeak();
public Boolean hasFeathers();

}

The class that implements the Animal interface to describe Cat:

package org.springaop.chapter.three.autoproxy.domain;

public class Cat implements Animal{

public boolean hasFur() {
return true;
}

public Integer getNumberPaws() {
return 4;
}

public Boolean hasTail() {
return true;
}

public Boolean hasHotBlood() {
return true;
}

public void setSpecies(String species) {
this.species = species;
}

public String getSpecies() {
return species;
}

public String getColour() {
return colour;
}

public void setColour(String colour) {
this.colour = colour;
}

private String species, colour;
}

The class that implements Animal and Bird to describe a Seabird:

package org.springaop.chapter.three.autoproxy.domain;

public class Seabird implements Animal,Bird{

public Integer getNumberPaws() {
return 2;
}

public Boolean hasTail() {
return false;
}

public Boolean hasBeak() {
return true;
}

public Boolean hasFeathers() {
return true;
}

public boolean hasFur() {
return false;
}

public Boolean hasHotBlood() {
return false;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

private String name;
}

AnimalAdvice containing just the log with the target class, the invoked method, and the result.

package org.springaop.chapter.three.autoproxy;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class AnimalAdvice implements MethodInterceptor {

public Object invoke(MethodInvocation invocation) throws Throwable {
Logger log = Logger.getLogger(Constants.LOG_NAME);
StringBuilder sb = new StringBuilder();
sb.append("Target Class:").append(invocation.getThis()).append("n").append(invocation.getMethod()).append("n");

Object retVal = invocation.proceed();

sb.append(" return value:").append(retVal).append("n");
log.info(sb.toString());
return retVal;
}
}

The configuration file applicationContext.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">


<bean id="tiger" class="org.springaop.chapter.three.autoproxy.domain.Cat">
<property name="species" value="tiger"/>
<property name="colour" value="tear stripes"/>
</bean>

<bean id="albatross" class="org.springaop.chapter.three.autoproxy.domain.Seabird">
<property name="name" value="albatross"/>
</bean>


<!-- Pointcut -->
<bean id="methodNamePointcut" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedNames">
<list>
<value>has*</value>
<value>get*</value>
</list>
</property>
</bean>


<!-- Advices -->
<bean id="animalAdvice" class="org.springaop.chapter.three.autoproxy.AnimalAdvice"/>


<!-- Advisor -->
<bean id="animalAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut" ref="methodNamePointcut"/>
<property name="advice" ref="animalAdvice"/>
</bean>


<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="proxyTargetClass" value="true"/>
<property name="beanNames">
<list>
<value>tiger</value>
<value>albatross</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>animalAdvisor</value>
</list>
</property>
</bean>

</beans>

Application context contains two beans, tiger and albatross. The methodNamePointcut acts on the methods starting with has and get.

The animalAdvice (around advice) contains the logics to be executed, the animal advisor that links the animalAdvice to the methodNamePointcut, and the autoProxyCreator, where we declare just the beans' names and the list of interceptors' names.

package org.springaop.chapter.three.autoproxy;

public class AutoProxyTest {

public static void main(String[] args) {

String[] paths = { "org/springaop/chapter/three/autoautoproxy/applicationContext.xml" };

ApplicationContext ctx = new ClassPathXmlApplicationContext(paths);

Cat tiger = (Cat)ctx.getBean("tiger");
tiger.hasHotBlood();

Bird albatross = (Bird)ctx.getBean("albatross");
albatros.hasBeak();
}
}

The test class invokes two methods on the beans tiger and albatross.

Output:

Spring 2.5 Aspect Oriented Programming Create dynamic, feature-rich, and robust enterprise applications using the Spring framework
Published: February 2009
eBook Price: ₨587.06
Book Price: ₨400.00
See more
Select your format and quantity:

DefaultAdvisorAutoProxyCreator

With BeanNameAutoProxyCreator, we've seen that the configuration file's extension has reduced; but we can do better.

Using the previous example, we modify only the configuration file.

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean id="tiger" class="org.springaop.proxies.autoproxy.domain.Cat">
<property name="species" value="tiger"/>
<property name="colour" value="tear stripes"/>
</bean>

<bean id="albatross" class="org.springaop.chapter.three.autoproxy.domain.Seabird">
<property name="name" value="albatross"/>
</bean>

<!-- Pointcut -->
<bean id="methodNamePointcut" class="org.springframework.aop.support.NameMatchMethodPointcut">
<property name="mappedNames">
<list>
<value>has*</value>
<value>get*</value>
</list>
</property>
</bean>

<!-- Advices -->
<bean id="animalAdvice" class="org.springaop.chapter.three.autoproxy.AnimalAdvice"/>


<!-- Advisor -->
<bean id="animalAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut" ref="methodNamePointcut"/>
<property name="advice" ref="animalAdvice"/>
</bean>

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" >
<property name="proxyTargetClass" value="true"/>
</bean>

</beans>

With DefaultAdvisorAutoProxyCreator, we don't need to define anything, apart from declaring it. This is because it applies the proxies' creation for the classes concerned in the advisors' application through pointcuts. It's important to have advisors, and not any other type of interceptor, because the operation is based on advisors.

The result of the advices' application is the same as you can see from the output:

AbstractAdvisorAutoProxyCreator

In case one wants to create his or her own AutoproxyCreator, he or she can employ the DefaultAdvisorAutoProxyCreator superclass, which is the AbstractAdvisorAutoProxyCreator, just by extending it.

AutoProxyCreator with metadata

This autoproxy option concerns the possibility to employ annotations in the classes, for example to define transactions.

In order to be able to employ this type of configuration, we have to use DefaultAdvisorAutoProxyCreator, a CommonsAttributes bean that interprets source level metadata, and another bean that employs those attributes.

In order to employ the CommosAttributes bean, we must have in the classpath the Jakarta library Commons Attributes (http://commons.apache.org/attributes).

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
...

<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

<bean id="advisor" class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
<property name="transactionInterceptor" ref="transactionInterceptor" />
</bean>


<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributeSource">
<bean class="org.springframework.transaction.interceptor.AttributesTransactionAttributeSource">
<property name="attributes" ref="metadataAttributes" />
</bean>
</property>
</bean>

<bean id="metadataAttributes" class="org.springframework.metadata.commons.CommonsAttributes" />

<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"/>
</bean>

</beans>

The autoProxyCreator bean creates proxies according to what advisors in the application context indicate to it, or the advices to apply and the pointcuts where to apply them.

In the example case, it is composed by a transactionInterceptor, the rules of which are defined into classes through annotations. In order to interpret these annotations, which are the beans' attributes property, it uses the metadataAttributes bean, which is of the type CommonsAttributes.

This type of configuration is used to be employed mostly before JDK 1.5, and it requires a particular compilation task.

With the use of del JDK 1.5 or upward, configuration doesn't require the use of the bean CommonsAttributes to interpret annotations.

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
<property name="transactionInterceptor" ref="transactionInterceptor"/>
</bean>

<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributeSource">
<bean class="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"/>
</property>
</bean>

<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"/>
</bean>

</beans>

Autoproxy with AspectJ

We saw autoproxy's devices with the classic configuration of Spring. Now we're going to see a short introduction on proxies with AspectJ.

The use of AspectJ can be connected to two typologies: through code annotations or through XML schema. Here are the rules that define which beans are excluded from the autoproxy:

  • Proxy is not applied to beans that implement the interfaces BeanPostProcessor or BeanFactoryPostProcessor. The class AnnotationAwareAspectJAutoProxyCreator implements the interface BeanPostProcessor, which allows the class to modify the life cycle of beans on which a proxy must be created and applied.
  • Classes with annotations @AspectJ and classes that implement or extend any other AOP component are excluded from the autoproxy. This is because they aren't target classes, and they perform tasks in Spring AOP infrastructure.

Apart from the beans that belong to these two cases, the other ones can be subject to proxies' self-creation. This is so if they are subject to aspects and advisors with the matching rules defined in pointcuts that are defined in the applicationContext.

Autoproxy with annotation

If we use annotations, we will tell Spring that proxies must be created according to them:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>
...
</beans>

AnnotationAwareAspectJAutoProxyCreator must be declared only one time. It's used by Spring to configure all the classes that have the annotation @Aspect, in order to create the proxy for the noted class and give it back for the execution of advices when a pointcut is matched.

Autoproxy with XML Schema

If we want automatic generation of proxies, we will use the tag <aop:aspectj-autoproxy/> through the AOP namespaces. Also this tag must be used one time. But in case of error, beans' proxies will be created only once, whereas if we declare AnnotationAwareAspectJAutoProxyCreator in several points of beans, we'll have several times the proxies' creation. The effect is anyway identical to the use of the bean AnnotationAwareAspectJAutoProxyCreator.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
...
<aop:aspectj-autoproxy/>
...
</beans>

If we want to force the use of CGLIB proxies, we will modify the tag aspectj-autoproxy in this way:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<aop:aspectj-autoproxy proxy-target-class="true"/>
...
</beans>

Summary

In this article, we have seen the important role of autoproxy on which Spring AOP is based. We saw how to reduce the configuration with the features provided by Spring for the automatic creation of beans with three types of autoproxy.

Spring 2.5 Aspect Oriented Programming Create dynamic, feature-rich, and robust enterprise applications using the Spring framework
Published: February 2009
eBook Price: ₨587.06
Book Price: ₨400.00
See more
Select your format and quantity:

About the Author :


Massimiliano Dessì

Massimiliano Dessì is an experienced Java developer, who started developing JEE applications in 2000. In 2004 he discovered the Spring Framework 1.0, and since then he has been one of its most enthusiastic users.

He works as a Software Architect and Engineer for Sourcesense (http://www.sourcesense.com), one of the leading European Open-Source System Integrators. Before joining Sourcesense, he worked as software architect for CRS4 (http://www.crs4.it). He's also an active technical writer, author of various articles, publications, and reviews available on http://www.jugsardegna.org/vqwiki/jsp/Wiki?MassimilianoDessi and on http://www.slideshare.net/desmax74/slideshows.

Massimiliano is also a frequent speaker at Users Groups conferences, including, Java Users Groups, SpringFrameworkUser Group, Javaday, and Linux Users Groups. He is one of the founders of Java User Group Sardinia (https://jugsardegna.dev.java.net/ and http://www.jugsardegna.org), the founder of "Spring Framework Italian User Group", "Jetspeed Italian User Group" and "Groovy Italian User Group".

He maintains a personal weblog at: http://jroller.com/page/desmax and lives in Cagliari, Sardinia with his family.

Books From Packt

Spring Web Flow 2 Web Development
Spring Web Flow 2 Web Development

EJB 3 Developer Guide
EJB 3 Developer Guide

JBoss Tools 3 Developers Guide
JBoss Tools 3 Developers Guide

Tapestry 5: Building Web Applications
Tapestry 5: Building Web Applications

JBoss Portal Server Development
JBoss Portal Server Development

Grails 1.0 Web Application Development
Grails 1.0 Web Application Development

ZK Developer’s Guide
ZK Developer’s Guide

Apache OFBiz Development: The Beginner's Tutorial
Apache OFBiz Development: The Beginner's Tutorial

Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software