ПредишенСледващото

динамично прокси

Някои теория ... прокси клас се създава чрез обаждане метод Proxy.getProxyClass която приема клас товарач и интерфейс масив (интерфейси), и се връща java.lang.Class обект клас, който се зарежда посредством предава клас товарач и приспособления предава интерфейси масив ,

На преминалите параметри имат редица ограничения:
  1. Всички обекти в масив от интерфейси трябва да бъдат интерфейси. Те не могат да бъдат класове или примитиви.
  2. В масива на интерфейси не може да бъде два еднакви обекти.
  3. Всички интерфейси в масива интерфейси трябва да бъдат натоварени на клас товарач, който се предава в метод getProxyClass.
  4. Всички непублични интерфейси трябва да бъдат определени в една и съща опаковка, в противен случай, генерирани прокси клас няма да бъде в състояние да прилага всички от тях.
  5. През всеки две интерфейси може да бъде методът със същите параметри име и подпис, но с различни видове връщане стойност.
  6. дължина Array ограничени интерфейси 65535 та интерфейси. Не Java класа не може да изпълнява повече от 65,535 интерфейси (и искам!).

Ако някое от горните ограничения е нарушено - ще бъдат хвърлени IllegalArgumentException. и ако масив от интерфейси интерфейс е нула, а след това NullPointerException е хвърлен.

Свойства на динамично прокси клас
  1. Класът на прокси е публично, е оборудван с модификатор окончателно и не е абстрактен.
  2. Името на класа на пълномощник по подразбиране не е определена, но започва от $ Proxy. Всичко пространство от имена, които започват да текат Proxy $ запазени за прокси класове.
  3. Класът прокси наследява от java.lang.reflect.Proxy.
  4. А прокси клас изпълнява всички интерфейси, предавани в създаването, с цел предаване.
  5. Ако прокси клас изпълнява непублична интерфейс, а след това ще се генерира в пакета, който определя най-непублична интерфейс. Като цяло, опаковка, в която класа прокси се генерира несигурност.
  6. метод Proxy.isProxyClass връща вярно за класовете, създаден с помощта на Proxy.getProxyClass и за класа обекти, създадени с помощта Proxy.newProxyInstance и фалшива друго. Този метод използва подсистемата за сигурност на Java и е необходимо да се разбере, че за един клас просто наследена от java.lang.reflect.Proxy го връща лъжа.
  7. java.security.ProtectionDomain за класа на прокси е същата като за класове система изтеглени фърмуера-товарач, например - за java.lang.Object. Това е логично, тъй като кодът на прокси клас се създава от JVM и няма причина да не вярвате на себе си.
Един пример за динамичен прокси класа и нейните свойства

прокси клас конструктор приема само един аргумент - интерфейса за изпълнение InvocationHandler. В съответствие с това прокси обект клас може да бъде създаден чрез отражение, като се обадите на обект newInstance клас. Въпреки това, има и друг начин - да се предизвика метод Proxy.newProxyInstance. който се заема с класа товарач включва набор от интерфейси, които ще осъществяват класа пълномощник, и на обекта, който реализира InvocationHandler. В действителност, този метод комбинира получи класа прокси използване Proxy.getProxyClass и създаде съд от този клас чрез отражение.

Свойствата на класа прокси създадени например, както следва:

  1. прокси обект клас води до всички интерфейси в масива на интерфейси мина. Ако Idemo - един от най-предавани интерфейси, прокси instanceof операция Idemo винаги ще се върне вярно. и експлоатацията (Idemo) прокси попълнена правилно.
  2. Proxy.getInvocationHandler статичен метод връща манипулатор повикване премина при създаването на инстанция на класа на пълномощник. Ако бъде приет в този метод не е обект е инстанция на класа на пълномощник, като ще бъдат хвърлени IllegalArgumentException изключение.
  3. повикване манипулатор клас изпълнява InvocationHandler интерфейс. който дефинира метод Invoke. имаща следния подпис:

публичен обект Invoke (обект прокси. метод метод. обект [] опцията) хвърля Throwable

Има прокси - инстанция на прокси клас, който може да се използва при обработката на повикване или друг метод. Вторият вариант - метод е инстанция на java.lang.reflect.Method. Стойността на този параметър - един от методите, дефинирани в която и да предава при създаването на прокси клас интерфейси или супер-интерфейси. Третият вариант - масива на метод аргументи. Аргументи на примитивни видове ще бъдат заменени с копия на техните класове, тайна, като java.lang.Integer или java.lang.Boolean. Специфичното приложение се позове на метода може да се промени масива.

Стойността върната от Invoke трябва да бъде от тип, съвместим с типа на стойността, върната от интерфейса, за които това се нарича обвивка. По-специално, ако методът на интерфейс връща примитивна стойност тип - това е необходимо, за да се върне копието на обвивката на примитивен тип. Ако тя се връща нула, и очакваната стойност на един примитивен тип - това ще бъде хвърлен NullPointerException. В случай на не-примитивни видове, метод на класа се позове на върнатата стойност трябва да е налице към класа на върнатата стойност от метода на интерфейс, в противен случай тя ще бъде изхвърлен ClassCastException.

Вътре метод Invoke трябва да хвърлят проверява само изключения, които са определени в подписването на нареченият метод или интерфейс, дадено им. В допълнение към тези видове изключения са позволени само да хвърли непроверени изключения (като java.lang.RuntimeException) или грешка (например, java.lang.Error). Ако се позове метод вътре в проверява изключение хвърлен несравними с тези, описани в интерфейса на метод подпис - това ще бъде само по изключение е хвърлен UndeclaredThrowableException.

методи хеш-код, за равенство и ToString, дефинирани в класа Object, същото ще се нарича не директно, а чрез позовават на метод на равна нога с всички методи на интерфейса. Други публични методи на класа на обекта ще се наричат ​​директно.

Обект на потребителя - е съвсем нормално, без магия.

Proxy.newProxyInstance - себе си за произхода на магия, параметрите на разговорите са както следва:

  • ClassLoader клас потребителя, за него малко по-ниско;
  • TipaClass масив. Той трябва да вземе набор от интерфейси. който реализира нашия клас (Потребител). Методи на тези връзки ще бъдат прихванати (invocationHandler-ти).
  • Екземпляр InvocationHandler. която е причинена от потребителя обект perehvatyvatmetody (в действителност, обажданията ще преминат през новосъздадената userProxy).

Изходът е пример за определен клас (прокси), което дава магически следната функционалност:

  • Извършва всички методи интерфейс, предавани в втори вход параметър Proxy.newProxyInstance за повикване (в този пример getName, setName, преименуване). В това той е подобен на лице;
  • При обаждане тези методи, нашата проба (например userProxy.setName), причинена метод InvocationHandler-позове (). InvocationHandler вече е взето решение за това как да действа -
    • обадете се на подходящия метод на реално лице клас
    • За да се направи нещо друго, в този случай,

    Това означава, че в нашия пример InvocationHandler просто показва името на нареченият метод на конзолата и да го кара да се съхранява на обекта. По този начин, преди всяко изпълнение на методи на потребителите ще се появи името на нареченият метод.

    Да кажем, че имаме "мазнини" клас с един куп начини, по който искаме да изпълнява едно и също действие - като например дърводобив, одитна пътека, сигурност, резултатите от сериализация. В класическия ООП, този проблем е решен, или копиране и поставяне, или освобождаването на всеки метод в класа, което не е удобно. И точно в този момент на помощ на магията, наречена отражение под формата на прокси. методи клас интерфейс да отделят достатъчно, за да се създаде обвивка, която ще изпълнява едно и също действие за всички методи (преди или след действителната метода на логика). Като цяло, това е джунгла AOP, които искат details'm тук.

    Къде е това "един клас", копие от който е получен в изхода Proxy.newProxyInstance?

    Това е създаден динамично клас създаден от масив от байтове.
    Верига Обадете се на: Proxy.newProxyInstance -> Proxy.getProxyClass -> sun.misc.ProxyGenerator.generateProxyClass
    Последният метод се връща масив от байтове, който след това се превръща чрез ClassLoader.defineClass в клас. и по-нататък newInstance.
    Резултатът е програма, която се генерира.
    Разбира се, аз искам да видя това, което генерира с Питър Джоунс.

    За щастие, можете да получите байткод генерирани клас, поставяйки вълшебно (и никой не знае) система имот «sun.misc.ProxyGenerator.saveGeneratedFi ле» за вярно, преди създаването на класа.

    Свързани статии

Подкрепете проекта - споделете линка, благодаря!