Uvod u cglib

1. Pregled

U ovom ćemo članku pogledati cglib (Biblioteka generacije koda). To je bajtna knjižnica instrumentacija koja se koristi u mnogim Java okvirima, poput Hibernate ili Proljeće. Instrumentacija bytecode-a omogućuje manipulaciju ili stvaranje klasa nakon faze kompajliranja programa.

2. Ovisnost Mavena

Koristiti cglib u svoj projekt samo dodajte ovisnost o Mavenu (najnoviju verziju možete pronaći ovdje):

 cglib cglib 3.2.4 

3. Cglib

Predmeti u Javi učitavaju se dinamički tijekom izvođenja. Cglib koristi ovu značajku Java jezika kako bi omogućio dodavanje novih klasa u već pokrenut Java program.

Hibernate koristi cglib za generiranje dinamičkih proxyja. Na primjer, neće vratiti puni objekt pohranjen u bazi podataka, ali vratit će instrumentiranu verziju pohranjene klase koja lijeno učitava vrijednosti iz baze podataka na zahtjev.

Popularni podsmiješni okviri, poput Mockito, koristiti cglib za metode ruganja. Mock je instrumentirana klasa u kojoj se metode zamjenjuju praznim implementacijama.

Pogledat ćemo najkorisnije konstrukcije iz cglib.

4. Implementacija korištenja proxyja cglib

Recimo da imamo a PersonService razred koji ima dvije metode:

javna klasa PersonService {javni niz sayHello (naziv niza) {return "Hello" + ime; } public Integer lengthOfName (ime niza) {return name.length (); }}

Primijetite da se prva metoda vraća Niz i onaj drugi Cijeli broj.

4.1. Vraćanje iste vrijednosti

Želimo stvoriti jednostavnu proxy klasu koja će presresti poziv a reci zdravo() metoda. The Pojačivač klasa omogućuje nam stvaranje proxyja dinamičkim proširivanjem a PersonService razred pomoću a setSuperclass () metoda iz Pojačivač razred:

Enhancer Enhancer = novi Enhancer (); enhancer.setSuperclass (PersonService.class); enhancer.setCallback ((FixedValue) () -> "Zdravo Tome!"); PersonService proxy = (PersonService) enhancer.create (); Niz res = proxy.sayHello (null); assertEquals ("Zdravo, Tom!", res);

The FixedValue je sučelje za povratni poziv koje jednostavno vraća vrijednost iz posredovane metode. Izvršenje reci zdravo() metoda na proxyju vratila je vrijednost navedenu u proxy metodi.

4.2. Vraćanje vrijednosti, ovisno o potpisu metode

Prva verzija našeg proxyja ima neke nedostatke jer nismo u mogućnosti odlučiti koju metodu bi proxy trebao presresti i koju bi metodu trebalo pozvati iz superklase. Možemo koristiti a MethodInterceptor sučelje za presretanje svih poziva proxyju i odlučivanje želite li uputiti određeni poziv ili izvršiti metodu iz superklase:

Enhancer Enhancer = novi Enhancer (); enhancer.setSuperclass (PersonService.class); enhancer.setCallback ((MethodInterceptor) (obj, method, args, proxy) -> {if (method.getDeclaringClass ()! = Object.class && method.getReturnType () == String.class) {return "Hello Tom!" ;} else {vratiti proxy.invokeSuper (obj, args);}}); PersonService proxy = (PersonService) enhancer.create (); assertEquals ("Zdravo Tom!", proxy.sayHello (null)); int lengthOfName = proxy.lengthOfName ("Mary"); assertEquals (4, lengthOfName);

U ovom primjeru presrećemo sve pozive kada potpis metode nije iz Objekt klase, što znači da je t.j. toString () ili hashCode () metode se neće presresti. Osim toga, presretamo samo metode iz a PersonService koji vraća a Niz. Nazovite a lengthOfName () metoda neće biti presretnuta jer je njezin povratni tip Cijeli broj.

5. Stvoritelj graha

Još jedan koristan konstrukt iz cglib je BeanGenerator razred. Omogućuje nam dinamičko stvaranje graha i dodavanje polja zajedno s metodama postavljanja i dobivanja. Alati za generiranje koda mogu ga koristiti za generiranje jednostavnih POJO objekata:

BeanGenerator beanGenerator = novi BeanGenerator (); beanGenerator.addProperty ("ime", String.class); Objekt myBean = beanGenerator.create (); Postavljač metode = myBean.getClass (). GetMethod ("setName", String.class); setter.invoke (myBean, "neku vrijednost niza postavila cglib"); Metoda getter = myBean.getClass (). GetMethod ("getName"); assertEquals ("neku vrijednost niza postavila cglib", getter.invoke (myBean));

6. Stvaranje Mixina

A mixin je konstrukcija koja omogućuje kombiniranje više objekata u jedan. Možemo uključiti ponašanje nekoliko klasa i izložiti to ponašanje kao jednu klasu ili sučelje. The cglib Mixini dopuštaju kombinaciju nekoliko predmeta u jedan objekt. Međutim, da bi to učinili svi objekti koji su uključeni u mixin moraju biti podržani sučeljima.

Recimo da želimo stvoriti kombinaciju dva sučelja. Moramo definirati sučelja i njihove implementacije:

javno sučelje Interface1 {String first (); } javno sučelje Interface2 {String second (); } javna klasa Class1 implementira Interface1 {@Override public String first () {return "prvo ponašanje"; }} javna klasa Class2 implementira Interface2 {@Override public String second () {return "drugo ponašanje"; }} 

Sastaviti implementacije Sučelje1 i Sučelje2 moramo stvoriti sučelje koje ih oboje proširuje:

javno sučelje MixinInterface proširuje Interface1, Interface2 {}

Korištenjem a stvoriti() metoda iz Mixin razreda u koje možemo uključiti ponašanja Razred1 i Razred2 u a MixinInterface:

Mixin mixin = Mixin.create (nova klasa [] {Interface1.class, Interface2.class, MixinInterface.class}, novi objekt [] {nova klasa1 (), nova klasa2 ()}); MixinInterface mixinDelegate = (MixinInterface) mixin; assertEquals ("prvo ponašanje", mixinDelegate.first ()); assertEquals ("drugo ponašanje", mixinDelegate.second ());

Metode pozivanja na mixinDelegate pozvat će implementacije iz Razred1 i Razred2.

7. Zaključak

U ovom smo članku gledali cglib i njegove najkorisnije konstrukcije. Stvorili smo proxy koristeći Pojačivač razred. Koristili smo a BeanCreator i na kraju, stvorili smo a Mixin to je uključivalo ponašanja drugih razreda.

Cglib se opsežno koristi u okviru Proljeća. Jedan od primjera cglib proxyja prema Springu je dodavanje sigurnosnih ograničenja pozivima metoda. Umjesto izravnog poziva metode, Spring sigurnost prvo će provjeriti (putem proxyja) prolazi li navedena sigurnosna provjera i delegirati stvarnu metodu samo ako je ova provjera bila uspješna. U ovom smo članku vidjeli kako stvoriti takav proxy za svoju svrhu.

Provedbu svih ovih primjera i isječaka koda možete pronaći u projektu GitHub - ovo je Maven projekt, pa bi ga trebalo lako uvesti i pokrenuti kakav jest.


$config[zx-auto] not found$config[zx-overlay] not found