Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anyone have a Spring AOP @DeclareParents example?

I've been trying to get this to work for a few days and have been failing miserably at it. I cannot seem to get my class cast properly to an Introduced interface. I'm using Spring 3.0.5.

Does anyone have a complete working example of a project that uses @DeclareParents? Or the XML equivalent? I have found a bunch of snippets on the web, but haven't had success in getting those to work either.

This is my first time trying Introductions, but am having a lot of difficulty getting this to work. I've read through the Spring docs and the AspectJ docs as well as well as the forums but still cannot get this to work. I thought created the classes/interfaces correctly, but when I try to cast the Advised object to the interface, I get a cast error.

Target:

@Entity
@Table(name = "item")
public class Item implements java.io.Serializable {

    private long id;
    private Integer mainType;
    private Integer subType;
    private String brandName;
    private String itemName;
    private Date releaseDate;
    private Date retireDate;
    private String fileName;
    private String thumbnailName;
    private String dimension;
    private boolean active;
    private boolean unlocked;
    private Integer unlockCost;
    private boolean owned;

    public Item() {
    }

    ...
    // bunch of getters and setters
    ...
}

Interface:

public interface AbstractBaseEntity {

    /**
     * @return the customAttributes
     */
    public Object getCustomAttribute(String name);

    /**
     * @param customAttributes the customAttributes to set
     */
    public void setCustomAttribute(String name, Object value);

}

Implementation:

public class AbstractBaseEntityImpl implements AbstractBaseEntity {

    /**
     * Map of custom attributes that can be mapped for the specific entity
     */
    @Transient
    protected Map customAttributes = new ConcurrentHashMap();

    /**
     * @return the customAttributes
     */
    public Object getCustomAttribute( String name ) {
        return customAttributes.get(name);
    }

    /**
     * @param customAttributes the customAttributes to set
     */
    public void setCustomAttribute(String name, Object value) {
        this.customAttributes.put(name, value);
    }

}

Aspect:

    @DeclareParents(value="com.fwl.domain.model.*+", defaultImpl=AbstractBaseEntityImpl.class)
    public AbstractBaseEntity mixin;

However, when I pass my introduced object to a method as an Object parameter, checking if it is an instanceof AbstractBaseEntity, it returns false.

    public void localize(Object entity, Locale locale) {
        List cachedFields;
            if (entity == null)
                // do nothing
                return;

            // check if the entity is already localized
            if( entity instanceof AbstractBaseEntity)
                // already localized so nothing to do
                return;

...
...
}

Is there anyway to ensure that the introduction is being done properly? Anyway to determine why I cannot cast it as an AbstractBaseEntity?

Any help would be greatly appreciated.

Thanks,

Eric

like image 280
Eric B. Avatar asked Jul 04 '11 03:07

Eric B.


People also ask

Where we can use Spring AOP?

Where to use Spring Aspect Oriented Programming. Some of the cases where AOP is frequently used: To provide declarative enterprise services. For example, as declarative transaction management. It allows users for implementing custom aspects.

Does Spring AOP affect performance?

As far as performance is concerned, compile-time weaving is much faster than runtime weaving. Spring AOP is a proxy-based framework, so there is the creation of proxies at the time of application startup. Also, there are a few more method invocations per aspect, which affects the performance negatively.

How do I enable AOP in spring?

For using Spring AOP in Spring beans, we need to do the following: Declare AOP namespace like xmlns:aop=“https://www.springframework.org/schema/aop” Add aop:aspectj-autoproxy element to enable Spring AspectJ support with auto proxy at runtime.


1 Answers

I have working example, but I know that the question is very old.
Basic Interface:

package pl.beans;

public interface Performance {
    public void perform();
}

implementation of Performance:

package pl.beans;

import java.util.Random;

import org.springframework.stereotype.Component;

@Component
public class Actor implements Performance {

private static final String WHO = "Actor: ";

@Override
public void perform() {
    System.out.println(WHO+"Making some strange things on scene");
    int result = new Random().nextInt(5);
    if(result == 0) {
        throw new IllegalArgumentException(WHO+"Actor falsified");
    }

}

}

New interface:

package pl.introduction;

public interface Crazy {

    public void doSomeCrazyThings();

}

Implementation of new interface:

package pl.introduction;

public class CrazyActor implements  Crazy {

@Override
public void doSomeCrazyThings() {
    System.out.println("Ługabuga oooo  'Performer goes crazy!'");

    }

}

Aspect:

package pl.introduction;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;

@Aspect
public class CrazyIntroducer {

    @DeclareParents(value="pl.beans.Performance+", defaultImpl=pl.introduction.CrazyActor.class)
    public static Crazy shoutable;

}

JavaConfig:

package pl.introduction;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

import pl.beans.Actor;
import pl.beans.Performance;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class Config {

    @Bean
    public CrazyIntroducer introducer () {
        return new CrazyIntroducer();
    }

    @Bean
    public Performance performance() {
        return new Actor();
    }
}

And test which shows that introduction working:

package pl.introduction;

import static org.junit.Assert.assertTrue;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import pl.beans.Performance;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = pl.introduction.Config.class)
public class IntroductionTest {

@Autowired
private Performance performance;

@Test
public void shoutTest() {
    try {
        performance.perform();

    } catch (IllegalArgumentException e) {
        System.out.println(e);
    }

    assertTrue(performance instanceof Crazy);
    ((Crazy) performance).doSomeCrazyThings();

    }
}
like image 138
DBadura Avatar answered Oct 15 '22 08:10

DBadura