2013-01-16 9 views

Odpowiedz

8

Odbicie to potężna konstrukcja, która jest często używana przez podstawowe biblioteki, takie jak Guice i Hibernate, aby ułatwić życie. Jest często używany tam, gdzie klasa musi być skonfigurowana, a następnie utworzona w locie. Na przykład:

public Strategy prepare(String clazz, Properties config) throws ClassNotFoundException, InstantiationException, IllegalAccessException { 
    Class<?> clazz = Class.forName(clazz); 
    Strategy strategy = (Strategy) clazz.newInstance(); 
    strategy.initialise(config); 
    return strategy; 
} 

W tym miejscu parametr clazz określa klasę do utworzenia instancji. Zakłada się, że klasa będzie podklasą klasy/interfejsu Strategii. Jest on następnie inicjowany z ustawieniami przekazywanymi za pośrednictwem parametru konfiguracyjnego. Pozwala to na wysoce konfigurowalne/dynamiczne środowisko.

Jednak odbicie często prowadzi do bardzo niebezpiecznego (i złośliwego) kodu, dlatego należy unikać refleksji, chyba że jest to absolutnie konieczne. Pamiętaj też, że odbicie jest wolniejsze niż bezpośrednie połączenie. Oto rzeczywisty przykład wyciągnięty z systemu produkcyjnego, jak NIE używać odbicia.

private static CacheManager getRawInstance() { 
    lock.lock(); 
    try { 
     final Field field = CacheManager.class.getDeclaredField("singleton"); 
     field.setAccessible(true); // << -- ?? 
     return (CacheManager) field.get(CacheManager.class); 
    } catch (Exception e) { 
     logger.error(e.getMessage(), e); 
     return null; 
    } finally { 
     lock.unlock(); 
    } 
} 

Tutaj pole prywatne w ehcache jest zmieniane i dostępne. To jest naprawdę złe kodowanie.

+1

Czekaj, Field.setAccessible (true) został wykorzystany w produkcji? ?? Zgaduję, że był to interesujący dzień, kiedy znaleziono ten klejnot. – Dan

+0

Tak, Dan, rzeczywiście ... zamek polerował klejnot trochę więcej (co stało się z "zsynchronizowanym"?). Problem został wykryty, gdy ehcache zaczął źle funkcjonować w innych częściach systemu (ignorując konfigurację itp.) Po uwzględnieniu tego faktu ... został on pozostawiony bez zmian z komentarzem jako ostrzeżeniem. To była dobra lekcja. Pokazuje, jak niebezpieczny może być kod odbicia. –

1

TechExchange wykonał świetną robotę wyjaśniając refleksję. Odbicie wydaje się być czarną owcą na Jawie. Zawsze słyszę ludzi, którzy twierdzą, że to jest buggy i podatny na błędy, ale okazało się, że jest całkiem stabilny i wydajny, gdy jest dobrze zrobiony. Powiem, że należy go unikać i wypróbować bibliotekę introspekcji w pisaniu natywnego kodu refleksyjnego. Introspekcja to to samo, co odbicie, ogólnie po prostu biblioteka zbudowana na bazowej bibliotece refleksji. Spring i Apache-commons mają świetne narzędzia, jeśli pracujesz z fasolą.

Wiosna i Apache tylko docelowe cele, niestety, nie żyję w świecie fasoli. Niektóre z obiektów, z którymi miałem pracować, to Boolean "to" metody i znalazłem się, pisząc kod odbicia.

W każdym razie jest tutaj prosty kod refleksyjny, który przechowuje każdą publiczną metodę z 0 argumentami.

public void foo(final Class _class){ 
    List<Method> methods = new ArrayList<Method>(){{ 
     for(Method method : _class.getMethods()) { 

      if(Modifier.isPublic(method.getModifiers()) 
       && method.getGenericParameterTypes().length == 0){ 

      add(method); 
     } 
    }}; 
} 
Powiązane problemy