4 min read

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 

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:

LEAVE A REPLY

Please enter your comment!
Please enter your name here