Announcement Announcement Module
Collapse
No announcement yet.
[very newbie] - Problems with Spring AOP Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • [very newbie] - Problems with Spring AOP

    Hi,

    Following the Spring in Action book (but actually writing my own example) I wanted to experiment AOP. So I created a very simple logger class:

    Code:
    package uk.co.jemos.tests.aop;
    
    import java.lang.reflect.Method;
    import java.util.Date;
    
    import org.apache.log4j.Logger;
    
    
    
    public class JemosLogger {
    	
    	private static final Logger LOG = Logger.getLogger(JemosLogger.class);
    	
    	public void logBefore(Method m) {
    		LOG.info("Starting method " + m.getName() + "on: " + new Date());
    	}
    	
    	public void logAfter(Method m) {
    		LOG.info("Ending method " + m.getName() + "on: " + new Date());
    	}
    
    }
    I then created a logger adviser as follows:

    Code:
    package uk.co.jemos.tests.aop;
    
    import java.lang.reflect.Method;
    
    import org.springframework.aop.AfterReturningAdvice;
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.aop.ThrowsAdvice;
    
    public class LoggerAdvice implements MethodBeforeAdvice, AfterReturningAdvice,
    		ThrowsAdvice {
    
    	public void before(Method arg0, Object[] arg1, Object arg2)
    			throws Throwable {
    		logger.logBefore(arg0);
    
    	}
    
    	public void afterReturning(Object arg0, Method arg1, Object[] arg2,
    			Object arg3) throws Throwable {
    		logger.logAfter(arg1);
    	}
    	
    	private JemosLogger logger;
    	public void setLogger(JemosLogger logger) {
    		this.logger = logger;
    	}
    
    }
    I then have a very simple interface:

    Code:
    package uk.co.jemos.tests;
    
    public interface GreetingService {
    	
    	public void sayGreeting();
    
    }
    And it's implementation class:

    Code:
    package uk.co.jemos.tests;
    
    public class GreetingServiceImpl implements GreetingService {
    
    	private String greeting;
    	
    	public void sayGreeting() {
    		System.out.println(getGreeting());
    
    	}
    	
    	public GreetingServiceImpl() {
    		// TODO Auto-generated constructor stub
    	}
    	
    	public GreetingServiceImpl(String greeting) {
    		this.greeting = greeting;
    	}
    
    	public String getGreeting() {
    		return greeting;
    	}
    
    	public void setGreeting(String greeting) {
    		this.greeting = greeting;
    	}
    
    }
    Code:
    package uk.co.jemos.tests;
    
    import static org.junit.Assert.assertNotNull;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    
    /**
     * Unit test for simple App.
     */
    public class GreetingServiceTest {
    	
    	
    	public void testGreeting() throws Exception {
    		
    		ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
    		
    		GreetingService service = (GreetingService) context.getBean("greetingService");
    		
    		assertNotNull("Spring didn't return the desired object", service);
    		
    		service.sayGreeting();
    		
    	}
        
    
    }

    When I run the Junit test the output doesn't show the logging activity.
    So I take my aspect didn't run. Have you got any explanation for this?

    Please find the bean configuration file attached.

    Thanks.

    M.

  • #2
    It is nice that you define an advisor but you didn't define anything which does something with your advisor. You will need to register a proxy creator.

    Comment


    • #3
      Originally posted by Marten Deinum View Post
      It is nice that you define an advisor but you didn't define anything which does something with your advisor. You will need to register a proxy creator.
      Could you please make an example?

      Comment


      • #4
        Proxy creator can be injected like shown below. There may be many other ways(using aop tags) of doing the same thing though. The PersonImpl eventually is being injected with a SimpleAdvice.

        <beans>
        <bean id="iPerson" class="PersonImpl">
        <property name="email">
        <value>[email protected]</value>
        </property>
        </bean>

        <bean id="personFactory" class="org.springframework.aop.framework.ProxyFact oryBean">
        <property name="proxyInterfaces">
        <list>
        <value>IPerson</value>
        </list>
        </property>
        <property name="target">
        <ref local="iPerson"/>
        </property>
        <property name="interceptorNames">
        <list>
        <value>advice</value>
        </list>
        </property>
        </bean>
        <bean id="advice" class="SimpleAdvice"/>

        <bean id="advisor" class="org.springframework.aop.support.DefaultPoin tcutAdvisor">
        <property name="advice">
        <ref local="advice"/>
        </property>

        <property name="pointcut">
        <bean class="org.springframework.aop.support.JdkRegexpMe thodPointcut">
        <property name="pattern">
        <value>.*foo.*</value>
        </property>
        </bean>
        </property>
        </bean>

        </beans>

        Comment


        • #5
          When posting code please use code tags.

          Whilst the above works it will need you to specify a ProxyFactoryBean for each bean, which is a bit heave. What I was talking/mentioning is simply specify a DefaultAdvisorAutoProxyCreator, that will pickup all Advisors and automatically create beans.

          However I still would favor the use of the aop:config stuff instead of the old FactoryBean and Advisor stuff.

          Comment


          • #6
            Thanks

            Thank you guys, I was finally able to run my first AOP example. The missing node in the configuration was exactly the definition of:

            Code:
            <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
            One thing I noticed though is the following: if in my advice I have a reference to another bean the aspect doesn't work! Example:

            This works:

            Code:
            <bean id="loggerAdvice" class="uk.co.jemos.tests.LoggerAdvice" />
            But this doesn't:

            Code:
            <bean id="loggerAdvice" class="uk.co.jemos.tests.LoggerAdvice" >
            		<property name="greetingService" ref="greetingService"></property>
            	</bean>
            I mean the code gets executed but the aspect doesn't get executed.

            M.

            Comment

            Working...
            X