apache mina : 用户自定义数据存储

来源:互联网 发布:java获取项目路径 编辑:程序博客网 时间:2024/06/05 07:52


Stores the user-defined attributes which is provided per  IoSession.  All user-defined attribute accesses in IoSession  are forwarded to  the instance of   IoSessionAttributeMap.


public interface IoSessionAttributeMap {    Object getAttribute(IoSession session, Object key, Object defaultValue);    Object setAttribute(IoSession session, Object key, Object value);    Object setAttributeIfAbsent(IoSession session, Object key, Object value);    Object removeAttribute(IoSession session, Object key);    boolean removeAttribute(IoSession session, Object key, Object value);    boolean replaceAttribute(IoSession session, Object key, Object oldValue, Object newValue);    boolean containsAttribute(IoSession session, Object key);    Set<Object> getAttributeKeys(IoSession session);    void dispose(IoSession session) throws Exception;}

   private static class DefaultIoSessionAttributeMap implements IoSessionAttributeMap {
        private final ConcurrentHashMap<Object, Object> attributes = new ConcurrentHashMap<Object, Object>(4);
   }

  在DefaultIoSessionDataStructureFactory 类中,使用ConcurrentHashMap 来保存用户自定义数据。


public final class AttributeKey implements Serializable {    /** The serial version UID */    private static final long serialVersionUID = -583377473376683096L;    /** The attribute's name */    private final String name;    public AttributeKey(Class<?> source, String name) {        this.name = source.getName() + '.' + name + '@' + Integer.toHexString(this.hashCode());    }}

使用AttributeKey 作为键。



在看看在netty 中是如何保存用户自定义数据的。

/** * Holds {@link Attribute}s which can be accessed via {@link AttributeKey}. * * Implementations must be Thread-safe. */public interface AttributeMap {    /**     * Get the {@link Attribute} for the given {@link AttributeKey}. This method will never return null, but may return     * an {@link Attribute} which does not have a value set yet.     */    <T> Attribute<T> attr(AttributeKey<T> key);    /**     * Returns {@code} true if and only if the given {@link Attribute} exists in this {@link AttributeMap}.     */    <T> boolean hasAttr(AttributeKey<T> key);}



public class DefaultAttributeMap implements AttributeMap {    @SuppressWarnings("rawtypes")    private static final AtomicReferenceFieldUpdater<DefaultAttributeMap, AtomicReferenceArray> updater;    static {        @SuppressWarnings("rawtypes")        AtomicReferenceFieldUpdater<DefaultAttributeMap, AtomicReferenceArray> referenceFieldUpdater =                PlatformDependent.newAtomicReferenceFieldUpdater(DefaultAttributeMap.class, "attributes");        if (referenceFieldUpdater == null) {            referenceFieldUpdater = AtomicReferenceFieldUpdater                            .newUpdater(DefaultAttributeMap.class, AtomicReferenceArray.class, "attributes");        }        updater = referenceFieldUpdater;    }    private static final int BUCKET_SIZE = 4;    private static final int MASK = BUCKET_SIZE  - 1;    // Initialize lazily to reduce memory consumption; updated by AtomicReferenceFieldUpdater above.    @SuppressWarnings("UnusedDeclaration")    private volatile AtomicReferenceArray<DefaultAttribute<?>> attributes;}

在Netty中默认AttributeMap是线程安全的,当AttributeMap被多个线程访问时,可以做到线程安全。

/** * Key which can be used to access {@link Attribute} out of the {@link AttributeMap}. Be aware that it is not be * possible to have multiple keys with the same name. * * @param <T>   the type of the {@link Attribute} which can be accessed via this {@link AttributeKey}. */@SuppressWarnings("UnusedDeclaration") // 'T' is used only at compile timepublic final class AttributeKey<T> extends AbstractConstant<AttributeKey<T>> {    private static final ConstantPool<AttributeKey<Object>> pool = new ConstantPool<AttributeKey<Object>>() {        @Override        protected AttributeKey<Object> newConstant(int id, String name) {            return new AttributeKey<Object>(id, name);        }    };    /**     * Returns the singleton instance of the {@link AttributeKey} which has the specified {@code name}.     */    @SuppressWarnings("unchecked")    public static <T> AttributeKey<T> valueOf(String name) {        return (AttributeKey<T>) pool.valueOf(name);    }    /**     * Returns {@code true} if a {@link AttributeKey} exists for the given {@code name}.     */    public static boolean exists(String name) {        return pool.exists(name);    }    /**     * Creates a new {@link AttributeKey} for the given {@param name} or fail with an     * {@link IllegalArgumentException} if a {@link AttributeKey} for the given {@param name} exists.     */    @SuppressWarnings("unchecked")    public static <T> AttributeKey<T> newInstance(String name) {        return (AttributeKey<T>) pool.newInstance(name);    }    @SuppressWarnings("unchecked")    public static <T> AttributeKey<T> valueOf(Class<?> firstNameComponent, String secondNameComponent) {        return (AttributeKey<T>) pool.valueOf(firstNameComponent, secondNameComponent);    }    private AttributeKey(int id, String name) {        super(id, name);    }}
/** * An attribute which allows to store a value reference. It may be updated atomically and so is thread-safe. * * @param <T>   the type of the value it holds. */public interface Attribute<T> {    /**     * Returns the key of this attribute.     */    AttributeKey<T> key();    /**     * Returns the current value, which may be {@code null}     */    T get();    /**     * Sets the value     */    void set(T value);    /**     *  Atomically sets to the given value and returns the old value which may be {@code null} if non was set before.     */    T getAndSet(T value);    /**     *  Atomically sets to the given value if this {@link Attribute}'s value is {@code null}.     *  If it was not possible to set the value as it contains a value it will just return the current value.     */    T setIfAbsent(T value);    /**     * Removes this attribute from the {@link AttributeMap} and returns the old value. Subsequent {@link #get()}     * calls will return {@code null}.     *     * If you only want to return the old value and clear the {@link Attribute} while still keep it in     * {@link AttributeMap} use {@link #getAndSet(Object)} with a value of {@code null}.     */    T getAndRemove();    /**     * Atomically sets the value to the given updated value if the current value == the expected value.     * If it the set was successful it returns {@code true} otherwise {@code false}.     */    boolean compareAndSet(T oldValue, T newValue);    /**     * Removes this attribute from the {@link AttributeMap}. Subsequent {@link #get()} calls will return @{code null}.     *     * If you only want to remove the value and clear the {@link Attribute} while still keep it in     * {@link AttributeMap} use {@link #set(Object)} with a value of {@code null}.     */    void remove();}


所有channel的抽象基类
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {

}

所有NioChannel的抽象基类

public abstract class AbstractNioChannel extends AbstractChannel {

}
所有NioByteChannel的抽象基类

public abstract class AbstractNioByteChannel extends AbstractNioChannel {

}

public class NioServerSocketChannel extends AbstractNioMessageChannel
                             implements io.netty.channel.socket.ServerSocketChannel {

}

public class NioSocketChannel extends AbstractNioByteChannel implements io.netty.channel.socket.SocketChannel {

}

从整体的设计与实现,每一次Netty都是在apache mina 之上的提升和优化, 也许会更加的简单方便。可以是因为先入为主的原因,总感觉apache  mina实现的更加简单,容易上手学习。


    

0 0
原创粉丝点击