1. Обзор <br /> агент - это шаблон проектирования, цель которого состоит в том, чтобы предоставить другой объект прокси для управления доступом к определенному объекту. Класс прокси отвечает за сообщения предварительной обработки для класса делегатов, фильтрацию сообщений и пересылки сообщений и выполнение последующей обработки после того, как сообщение выполняется классом делегатов. Чтобы поддерживать согласованность в поведении, классы прокси и классы делегирования обычно реализуют один и тот же интерфейс.
Согласно периоду создания агента, классы агентов можно разделить на два типа:
Статический прокси: программист создает прокси -класс или конкретный инструмент для автоматического генерации исходного кода, а затем скомпилируется его. То есть. Класс -файл класса прокси уже существует перед запуском программы.
Динамический прокси: используйте механизм отражения, чтобы создать и генерировать динамически при запуске программы.
Давайте кратко представим статический прокси, прежде чем реализовать динамический прокси -механизм.
2. Статический прокси <br /> Как упомянуто выше, как прокси, так и классы делегирования, как правило, должны реализовать один и тот же интерфейс. Следующее, чтобы сначала определить этот интерфейс:
Общественный интерфейс Service {public void add ();}Класс делегатов - это реализация интерфейса, определяемое следующим образом:
Общедоступный класс ServiceImpl реализует Service {public void add () {System.out.println («Добавить пользователь!»); }}Если мы хотим добавить несколько журналов в класс делегатов, класс прокси можно определить следующим образом:
Общедоступный класс ServiceProxy реализует услуги {Private Service Service; Public ServiceProxy (Service Service) {super (); this.service = service; } public void add () {System.out.println ("Service Start"); service.add (); System.out.println ("End Service End"); }}Напишите классы тестирования:
public Class Testmain {public static void main (string [] args) {service serviceImpl = new serviceImpl (); Service Proxy = New ServiceProxy (ServiceImpl); proxy.add (); }}Запустите тестовую программу, результаты следующие:
Из приведенного выше кода мы видим, что статический класс прокси может служить только конкретному интерфейсу. Если вы хотите обслуживать несколько типов объектов, вы должны прокси -серверы каждого объекта. Мы подумаем о том, могут ли все прокси -функции быть завершены через класс прокси, поэтому мы представили концепцию динамического прокси.
3. Dynamic Proxy Java's Dynamic Proxy в основном включает в себя два класса, Proxy и InvocationHandler.
Прокси: предоставляет набор статических методов для динамического генерации классов прокси и их объектов для набора интерфейсов.
// Метод 1: Этот метод используется для получения процессора вызова, связанного с указанным прокси -объектом. Статический vlocationhandler getInvocationHandler (объект прокси) // Метод 2: Этот метод используется для получения объекта класса динамического класса прокси, связанного с указанным загрузчиком класса и набором интерфейсов. Статический класс getProxyClass (ClassLoader Loader, класс [] интерфейсы) // Метод 3: Этот метод используется для определения того, является ли указанный объект класса динамическим классом прокси -класса статического логического лобного ягода (класс CL) // Метод 4: Этот метод используется для генерации динамических институтов класса прокси для указанного класса, загруженного класса, набора интерфейсов и набора. Статический объект NewProxyInstance (ClassLoader Loader, интерфейсы класса [], vococationHandler h)
InvocationHandler: это интерфейс вызова процессора, настраивает метод Invok, который используется для центральной обработки методов вызовов на объектах динамического прокси -класса, обычно в том, что прокси -доступ к классам делегирования реализован
// Этот метод отвечает за центральную обработку всех вызовов метода в классе динамического прокси. Первый параметр является как экземпляр класса прокси, а второй параметр - это объект метода, который называется // Третий метод - это параметр вызова. Процессы процессора вызовов или отправки в экземпляр класса делегата для передачи объекта выполнения invoke (Прокси -сервер, метод метода, объект [] args)
Для реализации динамического прокси для Java есть четыре конкретных шага:
1. Создайте свой собственный процессор вызовов, внедрив интерфейс InvocationHandler
2. Создать класс динамического прокси, указав объект ClassLader и набор интерфейсов для класса прокси -сервера
3. Получить конструктор класса динамического прокси -сервера через механизм отражения, и его единственный тип параметров - тип интерфейса класса Call Class
4. Создайте динамический экземпляр класса прокси через конструктор. Во время строительства объект процессора называется параметром и передается.
Ниже приведен пример реализации вашего собственного динамического прокси на основе четырех вышеуказанных шагов:
Класс реализации интерфейса и интерфейса (то есть класс делегирования) такой же, как и код приведенного выше статического прокси. Здесь мы будем реализовать интерфейс InvocationHandler для создания нашего собственного процессора вызовов.
Общедоступный класс ServiceHandle реализует vocationHandler {Private Object S; Public ServiceHandle (объект S) {this.s = s; } public Object Invoke (Object Proxy, метод метода, объект [] args) бросает throwable {System.out.println ("Service Start"); // Вызов означает вызов основополагающего метода, представленного этим объектом метода на указанном объекте с указанными параметрами объекта result = method.invoke (s, args); System.out.println ("End Service End"); результат возврата; }}Напишите классы тестирования:
public Class Testmain {public static void main (string [] args) {service service = new serviceImpl (); Vlocationhandler handler = new ServiceHandle (Service); Service s = (Service) proxy.newProxyInstance (service.getClass (). GetClassLoader (), service.getClass (). GetInterfaces (), Handler); S.Add (); }}Запустите тестовую программу, и результат такой же, как и статический прокси. Мы можем видеть, что приведенный выше код не имеет шагов 2 и 3, которые мы упоминали ранее, потому что статический метод Prox NewProxyInstance инкапсулировал эти два шага для нас. Конкретная внутренняя реализация заключается в следующем:
// Динамически создавать класс объект класса прокси для набора интерфейсов, включая интерфейс интерфейса через прокси -класс clazz = proxy.getProxyClass (ClassLoader, новый класс [] {interface.class, ...}); // Получить объект конструктора из созданного класса объекта через Constructor = clazz.getConstrustructor (new Classluctrashrashdlor. Создать динамический экземпляр класса прокси через интерфейс объекта конструктора Proxy = (интерфейс) constructor.newinstance (new Object [] {Handler});Внутренняя реализация функции NewProxyInstance - это:
Public Static Object NewProxyInstance (ClassLoader Loader, Class <?> [] Интерфейсы, volcocationHandler h) Throws OldalArgumentException {// Проверка H не пуст, в противном случае выбросьте Exception Objects.Requirenonlull (h); // Получить объект типа класса прокси, связанный с формулированием загрузчика класса, и набора интерфейсов конечного класса <?> [] Intfs = extfaces.clone (); // Проверьте, является ли объект класса интерфейса видным для загрузчика класса и точно такой же, как объект класса интерфейса, распознаваемый классом Loader Final SecurityManager SM = System.getSecurityManager (); if (sm! = null) {checkproxyaccess (Reflection.getCallerclass (), Loader, Intfs); } // Получить объект типа класса прокси, связанный с формулированием загрузчика класса, и набора интерфейсов класса <?> Cl = getProxyClass0 (Loader, Intfs); попробуйте {if (sm! = null) {checknewproxypermission (Reflection.getCallerclass (), cl); } // Получить объект конструктора посредством отражения и генерировать конечный конструктор класса прокси <?> Cons = cl.getConstructor (constructorparams); окончательный vocationHandler ih = h; if (! modifier.ispublic (cl.getModifiers ())) {accessController.doprivileged (new PrivilegedAction <void> () {public void run () {cons.SetAccessible (true); return null;}}); } return ons.newinstance (new Object [] {h}); } catch (allogalAccessException | instantiationException e) {бросить новый InternalError (e.toString (), e); } catch (vococationTargetException e) {throwable t = e.getCaue (); if (t ancessionof runtimeexception) {throw (runtimeexception) t; } else {бросить новый InternalError (t.toString (), t); }} catch (nosuchmethodexception e) {бросить новый InternalError (e.toString (), e); }} 4. Моделируйте и реализуйте класс прокси -сервера
Согласно вышеуказанному введению, мы можем сами имитировать и внедрить класс прокси:
Public Class Proxy {public Static Object newProxyInstance (класс Mawse, InvocationHandle h) выбрасывает exection {string rt = "/r/n"; String methodstr = ""; Method [] methods = mapace.getMethods (); для (метод M: методы) {methodstr+= "@override"+rt+"public void"+m.getName ()+"()"+rt+"{"+rt+"try {"+rt+"method md ="+inface.getname ()+". class.getmethod (/"+m.getname ()+"/"); "h.invoke (this, md);"+ rt+ "} catch (Exception e) {e.printstacktrace ();}"+ rt+ "}"; } String src = "test;"+ rt+ "Import java.lang.reflect.method;"+ rt+ "Общедоступный Class ServiceImpl2 реализует"+ inface.getName ()+ rt+ "{"+ rt+ "public serviceImpl2 (vocationHandle h)"+ rt+ "{+ rt+" test.invocationHandle h; "+ rt+ methodstr+"} "; String fileName = "d: /src/test/serviceimpl2.java"; // компиляция компиляции (src, имя файла); // загружать в память и создать объект экземпляра m = loadmemory (h); возврат М; } private static void compile (String src, String fileName) бросает ioException {file f = new File (filename); FileWriter FileWriter = new FileWriter (f); filewriter.write (src); filewriter.flush (); filewriter.close (); // Получить Java Compiler, предоставленную этой платформой, Javacompiler Compiler = ToolProvider.getSystemjavacompiler (); // Получить новый экземпляр, реализованный стандартным диспетчера файлов standardjavafilemanager filemanager = compiler.getstandardfilemanager (null, null, null); // Получение объекта файла, представляющего заданный файл iteerable it it it intis = filemanager.getJavafileObjects (имя файла); // Создать будущее компиляцию task t = compiler.getTask (null, filemanager, null, null, null, единицы); // выполнить эту задачу компиляции t.call (); filemanager.close (); } Частный статический объект Loadmemory (vococationHandle H) выбрасывает MalformedUrlexception, ClassNotFoundException, nosuchmethodexception, undantiationException, allogalAccessexception, vocationTargetException {url [] urls = new url [] {new URL ("file:/"+"d:/src/")}; // Загрузить класс и ресурс urlclassloader ul = new UrlClassLoader (URLS); Класс C = ul.loadClass ("test.serviceimpl2"); // Возвращает указанный общественный конструктор класса, представленного объектом класса. Конструктор Ctr = C.GetConstructor (vococationHandle.class); // Использование метода конструктора, представленного этим объектом CTRUCTOR CTR для создания нового экземпляра класса объявления метода конструктора, и инициализируйте экземпляр с указанным объектом параметра инициализации m = ctr.newinstance (h); возврат М; }}5. Резюме 1. Так называемый динамический прокси-это такой класс. Это класс, сгенерированный во время выполнения. При его генерировании вы должны предоставить ему набор интерфейсов, а затем изменить класс, чтобы утверждать, что он реализует эти интерфейсы. Тем не менее, он не выполнит существенную работу для вас, но возьмет на себя фактическую работу на основе обработчика параметров (то есть класса реализации интерфейса InvocationHandler), предоставленной при генерации экземпляра.
2. Прокси -дизайн делает его только прокси -сервером интерфейса поддержки. Механизм наследования Java определял, что динамический класс прокси не может реализовать динамический прокси для класса, потому что множественное наследование по сути невозможно в Java.
Выше приведено в этой статье, я надеюсь, что это будет полезно для каждого обучения.