web-dev-qa-db-ja.com

クラスがスーパークラスのアノテーションを継承することは可能ですか?

トランザクション管理にSpringFrameworkトランザクションアノテーションを使用しており、以下に示すようにabstract classアノテーション付き@Transactionalがあります。

package org.tts.maqraa.service;

import Java.util.Collection;
import Java.util.Iterator;
import Java.util.List;
import Java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.Query;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Parts of this code have been copied from JARVANA site.
 * 
 * @author Younis alomoush
 * 
 */
@Transactional(propagation=Propagation.REQUIRED)
public abstract class AbstractMaqraaService implements MaqraaService {


    private Logger logger = LoggerFactory.getLogger(this.getClass());


    private int defaultMaxResults = DEFAULT_MAX_RESULTS;

    @PersistenceContext(type=PersistenceContextType.TRANSACTION)
    private EntityManager em;
    /**
     * The {@link EntityManager} which is used by all query manipulation and
     * execution in this DAO.
     * 
     * @return the {@link EntityManager}
     */
    public  EntityManager getEntityManager(){

        return em;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.skyway.spring.util.dao.JpaDao#getTypes()
     */
    public abstract Set<Class<?>> getTypes();

    /*
     * (non-Javadoc)
     * 
     * @see org.skyway.spring.util.dao.JpaDao#store(Java.lang.Object)
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public <T extends Object> T store(T toStore) {
        return getEntityManager().merge(toStore);

    }

    /*
     * (non-Javadoc)
     * 
     * @see org.skyway.spring.util.dao.JpaDao#remove(Java.lang.Object)
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void remove(Object toRemove) {
        toRemove = getEntityManager().merge(toRemove);
        getEntityManager().remove(toRemove);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.skyway.spring.util.dao.JpaDao#flush()
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void flush() {
        getEntityManager().flush();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.skyway.spring.util.dao.JpaDao#refresh(Java.lang.Object)
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    public void refresh(Object o) {
        try {
            if (o != null) {
                if (o instanceof Java.util.Collection) {
                    for (Iterator<?> i = ((Collection<?>) o).iterator(); i
                            .hasNext();) {
                        try {
                            refresh(i.next());
                        } catch (EntityNotFoundException x) {
                            // This entity has been deleted - remove it from the
                            // collection
                            i.remove();
                        }
                    }
                } else {
                    if (getTypes().contains(o.getClass())) {
                        getEntityManager().refresh(o);
                    }
                }
            }
        } catch (EntityNotFoundException x) {
            // This entity has been deleted
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.skyway.spring.util.dao.JpaDao#setDefaultMaxResults(int)
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    public void setDefaultMaxResults(int defaultMaxResults) {
        this.defaultMaxResults = defaultMaxResults;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.skyway.spring.util.dao.JpaDao#getDefaultMaxResults()
     */
    public int getDefaultMaxResults() {
        return defaultMaxResults;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.skyway.spring.util.dao.JpaDao#executeQueryByNameSingleResult(Java
     * .lang.String)
     */
    @SuppressWarnings("unchecked")
    public <T extends Object> T executeQueryByNameSingleResult(String queryName) {
        return (T) executeQueryByNameSingleResult(queryName, (Object[]) null);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.skyway.spring.util.dao.JpaDao#executeQueryByNameSingleResult(Java
     * .lang.String, Java.lang.Object[])
     */

    @SuppressWarnings("unchecked")
    public <T extends Object> T executeQueryByNameSingleResult(
            String queryName, Object... parameters) {
        Query query = createNamedQuery(queryName, DEFAULT_FIRST_RESULT_INDEX,
                1, parameters);
        return (T) query.getSingleResult();
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.skyway.spring.util.dao.JpaDao#executeQueryByName(Java.lang.String)
     */
    public <T extends Object> List<T> executeQueryByName(String queryName) {
        return executeQueryByName(queryName, DEFAULT_FIRST_RESULT_INDEX,
                getDefaultMaxResults());
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.skyway.spring.util.dao.JpaDao#executeQueryByName(Java.lang.String,
     * Java.lang.Integer, Java.lang.Integer)
     */

    public <T extends Object> List<T> executeQueryByName(String queryName,
            Integer firstResult, Integer maxResults) {
        return executeQueryByName(queryName, firstResult, maxResults,
                (Object[]) null);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.skyway.spring.util.dao.JpaDao#executeQueryByName(Java.lang.String,
     * Java.lang.Object[])
     */

    public <T extends Object> List<T> executeQueryByName(String queryName,
            Object... parameters) {
        return executeQueryByName(queryName, DEFAULT_FIRST_RESULT_INDEX,
                getDefaultMaxResults(), parameters);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.skyway.spring.util.dao.JpaDao#executeQueryByName(Java.lang.String,
     * Java.lang.Integer, Java.lang.Integer, Java.lang.Object[])
     */
    @SuppressWarnings("unchecked")
    public <T extends Object> List<T> executeQueryByName(String queryName,
            Integer firstResult, Integer maxResults, Object... parameters) {
        Query query = createNamedQuery(queryName, firstResult, maxResults,
                parameters);
        return query.getResultList();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.skyway.spring.util.dao.JpaDao#createNamedQuery(Java.lang.String,
     * Java.lang.Integer, Java.lang.Integer)
     */

    public Query createNamedQuery(String queryName, Integer firstResult,
            Integer maxResults) {
        return createNamedQuery(queryName, firstResult, maxResults,
                (Object[]) null);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.skyway.spring.util.dao.JpaDao#createNamedQuery(Java.lang.String,
     * Java.lang.Integer, Java.lang.Integer, Java.lang.Object[])
     */

    public Query createNamedQuery(String queryName, Integer firstResult,
            Integer maxResults, Object... parameters) {
        Query query = getEntityManager().createNamedQuery(queryName);
        if (parameters != null) {
            for (int i = 0; i < parameters.length; i++) {
                query.setParameter(i + 1, parameters[i]);
            }
        }

        query.setFirstResult(firstResult == null || firstResult < 0 ? DEFAULT_FIRST_RESULT_INDEX
                : firstResult);
        if (maxResults != null && maxResults > 0)
            query.setMaxResults(maxResults);

        return query;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.skyway.spring.util.dao.JpaDao#executeQuery(Java.lang.String,
     * Java.lang.Integer, Java.lang.Integer, Java.lang.Object[])
     */
    @SuppressWarnings("unchecked")
    public <T extends Object> List<T> executeQuery(String queryString,
            Integer firstResult, Integer maxResults, Object... parameters) {
        Query query = createQuery(queryString, firstResult, maxResults,
                parameters);
        return query.getResultList();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.skyway.spring.util.dao.JpaDao#executeQuery(Java.lang.String,
     * Java.lang.Object[])
     */
    @SuppressWarnings("unchecked")
    public <T extends Object> List<T> executeQuery(String queryString,
            Object... parameters) {
        Query query = createQuery(queryString, DEFAULT_FIRST_RESULT_INDEX,
                getDefaultMaxResults(), parameters);
        return query.getResultList();
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.skyway.spring.util.dao.JpaDao#executeQuerySingleResult(Java.lang.
     * String)
     */
    @SuppressWarnings("unchecked")
    public <T extends Object> T executeQuerySingleResult(String queryString) {
        return (T) executeQuerySingleResult(queryString, (Object[]) null);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.skyway.spring.util.dao.JpaDao#executeQuerySingleResult(Java.lang.
     * String, Java.lang.Object[])
     */
    @SuppressWarnings("unchecked")
    public <T extends Object> T executeQuerySingleResult(String queryString,
            Object... parameters) {
        Query query = createQuery(queryString, DEFAULT_FIRST_RESULT_INDEX, 1,
                parameters);
        return (T) query.getSingleResult();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.skyway.spring.util.dao.JpaDao#createQuery(Java.lang.String,
     * Java.lang.Integer, Java.lang.Integer)
     */

    public Query createQuery(String queryString, Integer firstResult,
            Integer maxResults) {
        return createQuery(queryString, firstResult, maxResults,
                (Object[]) null);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.skyway.spring.util.dao.JpaDao#createQuery(Java.lang.String,
     * Java.lang.Integer, Java.lang.Integer, Java.lang.Object[])
     */
    public Query createQuery(String queryString, Integer firstResult,
            Integer maxResults, Object... parameters) {
        Query query = getEntityManager().createQuery(queryString);
        if (parameters != null) {
            for (int i = 0; i < parameters.length; i++) {
                query.setParameter(i + 1, parameters[i]);
            }
        }

        query.setFirstResult(firstResult == null || firstResult < 0 ? DEFAULT_FIRST_RESULT_INDEX
                : firstResult);
        if (maxResults != null && maxResults > 0)
            query.setMaxResults(maxResults);

        return query;
    }

    public final void log(LogLevel logLevel, String message,
            Object... messageParam) {

        switch (logLevel) {
        case TRACE:
            if (logger.isTraceEnabled()) {

                logger.trace(message, messageParam);
            }

            break;

        case DEBUG:
            if (logger.isDebugEnabled()) {

                logger.debug(message, messageParam);
            }
            break;

        case INFO:
            if (logger.isInfoEnabled()) {

                logger.info(message, messageParam);
            }
            break;

        case WARN:
            if (logger.isWarnEnabled()) {

                logger.warn(message, messageParam);
            }
            break;

        case ERROR:
            if (logger.isErrorEnabled()) {

                logger.error(message, messageParam);
            }
            break;

        default:
            throw new IllegalArgumentException("Log Level is not defined: "
                    + logLevel);

        }

    }

    public final void log(LogLevel logLevel,  String message, Throwable throwable) {

        switch (logLevel) {
        case TRACE:
            if (logger.isTraceEnabled()) {

                logger.trace(message, throwable);
            }

            break;

        case DEBUG:
            if (logger.isDebugEnabled()) {

                logger.debug(message, throwable);
            }
            break;

        case INFO:
            if (logger.isInfoEnabled()) {

                logger.info(message, throwable);
            }
            break;

        case WARN:
            if (logger.isWarnEnabled()) {

                logger.warn(message, throwable);
            }
            break;

        case ERROR:
            if (logger.isErrorEnabled()) {

                logger.error(message, throwable);
            }
            break;

        default:
            throw new IllegalArgumentException("Log Level is not defined: "
                    + logLevel);

        }

    }


    public enum LogLevel{

        TRACE, DEBUG, INFO, WARN, ERROR;

    }
}

また、私は別の具体的なクラスを持っています

package org.tts.maqraa.service;

import Java.lang.annotation.Annotation;
import Java.util.HashSet;
import Java.util.List;
import Java.util.Set;
import org.tts.maqraa.data.Student;


public class StudentsService extends AbstractMaqraaService {

    @Override
    public Set<Class<?>> getTypes() {
        Set<Class<?>> set = new HashSet<Class<?>>();
        set.add(Student.class);
        return set;
    }

    public Student registerStudent(Student student) {
        Annotation [] annotation = StudentsService.class.getAnnotations();
        System.out.println(annotation);
        return this.store(student);
    }

    public Student editStudent(Student student){
        return this.store(student);
    }

    public void deregisterStudent(Student student){
        this.remove(student);
    }

    public List<Student> findAllStudents(){
        return this.executeQueryByName("Student.findAll");
    }

}

メソッドレジスタの学生が、私が実際に@Transactionalアノテーションを見つけたアノテーションを調べるためのコードをすでに提供していることに気付いた場合。

これは、注釈の継承について話している別のリンクがあり、継承がまったくないと言っているという矛盾です。

このリンクを確認してください: http://fusionsoft-online.com/articles-Java-annotations.php

誰かが私がこの矛盾を解決するのを手伝ってくれる?

21
Mohammed Amr

アノテーションの継承は、基本的にメソッドまたはフィールドの継承と同じように機能します。

リフレクションを介してのみアノテーションにアクセスできるため、Classには2つの基本的なメソッドがあります。

  • getAnnotations()は、現在のクラスとそのスーパークラスのすべてのアノテーションを返します
  • getDeclaredAnnotations()は、現在のクラスのすべてのアノテーションを返します

あなたがリンクした記事が話している問題は、Method#getAnnotation(...)がメソッドが定義されているクラスのdeclaredAnnotations()にアクセスすることです。これは、上記のように、そのクラスで定義されたアノテーションのみを返し、それらは返しません。スーパークラスの。

つまり、@Transactionalアノテーションが付けられたメソッドの1つをオーバーライドする場合は、そこにアノテーションを追加する必要があります(または、フレームワークがクラ​​スアノテーションも調べる場合は、AbstractMaqraaServiceで宣言された@Transactionalを見つける必要があります)。 。

17
Thomas

はい、注釈に @Inherited が追加されている場合は可能です。たとえば、 @Transactional アノテーションには@Inheritedがあります。

ドキュメントから:

注釈タイプが自動的に継承されることを示します。継承されたメタアノテーションがアノテーションタイプ宣言に存在し、ユーザーがクラス宣言でアノテーションタイプをクエリし、クラス宣言にこのタイプのアノテーションがない場合、クラスのスーパークラスは自動的にアノテーションタイプを照会されます。このプロセスは、このタイプの注釈が見つかるか、クラス階層の最上位(オブジェクト)に到達するまで繰り返されます。このタイプのアノテーションを持つスーパークラスがない場合、クエリは問題のクラスにそのようなアノテーションがないことを示します。

このメタアノテーションタイプは、アノテーション付きタイプがクラス以外のものにアノテーションを付けるために使用される場合は効果がないことに注意してください。このメタアノテーションは、アノテーションがスーパークラスから継承されるだけであることにも注意してください。実装されたインターフェースの注釈は効果がありません。

@Transactionalのドキュメント:

@Target(value={METHOD,TYPE})
@Retention(value=RUNTIME)
@Inherited
@Documented
public @interface Transactional

オフトピック:Javaでは、注釈をサブタイプ化することはできません。

38
mprabhat