
Mixin Type can be very simple, like;
The Mixin Types of a Composite are ;
There is not a 1:1 correlation between Mixin Type and Mixin implementation. One can't even know if there are more or less of one over the other. That is because a Mixin implementation can implement less than one, one, or more than one Mixin Type.
It is also entirely possible that multiple implementation methods exists for a Mixin Type method. The mixin method resolution algorithm will provide a deterministic behavior of which implementation of a method is chosen. The algorithm is as follows;
For each declared method of all Mixin Types of a Composite;
This means that one Mixin implementation can 'override' a single method that a larger mixin implementation implements together with many other methods. So, just because a mixin implements MixinTypeA.method1() and has an implementation of MixinTypeA.method2(), doesn't mean that method2() is mapped to that mixin. This is very important to remember. The Envisage tool is capable of visualizing how Mixin Type methods are mapped to implementations.
Each method in the CompositeType interface MUST be backed by a mixin class.
Mixins are declared as annotations on the CompositeType interface.
public class SomethingMixin
implements Something
{
// State is allowed.
public void doSomething()
{
// do stuff...
}
}
If we have many interfaces defining many methods, that all must be backed by a mixin implementation, we simply list all the mixins required.
public interface Startable
{
boolean start();
void stop();
}
public interface Vehicle
{
void turn( float angle );
void accelerate( float acceleration );
// more methods
}
public interface Vehicle extends SpeedLocation, Crashable
{
}
public interface SpeedLocation
{
void turn( float angle );
void accelerate( float acceleration );
}
public abstract class SpeedMixin
implements SpeedLocation
{
// state for speed
public void accelerate( float acceleration )
{
// logic
}
}
Private Mixins are handled automatically. When Qi4j detects a @This annotation referring to a type that is not defined in the Composite Type interface, then that is a Private Mixin. The Mixin implementation class, however, must exist in the list of Mixins in the @Mixins annotation. But often, the Private Mixin only list internal Property methods in the Mixin Type, which will be satisfied by the standard PropertyMixin and hence always available.
This is particularly useful in Domain Driven Design, where you only want to expose domain methods, which are defined by the context where they are used. But the state of the Mixin should not be exposed out at all. For instance, if we have the Cargo interface like;
Location destination();
void changeDestination( Location newDestination );
}
public Location origin()
{
return state.origin().get();
}
public Location destination()
{
return state.destination().get();
}
public void changeDestination( Location newDestination )
{
state.destination().set( newDestination );
}
}
public interface CargoState
{
Property<Location> origin();
Property<Location> destination();
}
Experience shows that Generic Mixin implementations are rare, and should only be used in extreme cases. They are less frequent than Generic Concern or Generic SideEffect implementations, but inside the Qi4j API are a couple of Generic Mixin implementations that are always present to make the life of the developer easier, such as PropertyMixin, AssociationMixin, ManyAssociationMixin, NoopMixin. The first 3 are declared on the Composite and EntityComposite interfaces and automatically included if needed. They also serve as excellent example of what they can be used for.
public Object invoke( Object proxy, Method method, Object[] args )
throws Throwable
{
return state.getProperty( method );
}
public static class PropertyFilter
implements AppliesToFilter, Serializable
{
public boolean appliesTo( Method method, Class<?> mixin,
Class<?> compositeType,
Class<?> modifierClass )
{
return Property.class.isAssignableFrom( method.getReturnType() );
}
}
}
which seems to indicate that Generic Mixin implementations are likely to be used in integration of other technologies.
Typed Mixin implementations are much preferred in general business logic, as they will be first-class citizens of the IDE as well, for navigation, find usage, refactoring and many other common tasks. This is one of the main advantages of the Qi4j way of doing AOP compared to AspectJ et al, where "weaving" is something bolted onto an application's classes via regular expressions and known naming conventions, which can change in an instance by a developer being unaware of which PointCuts applies to his code.