Agent: Um das A-Objekt zu steuern, wird ein neues B-Objekt erstellt und das B-Objekt führt stattdessen alle Operationen des A-Objekts aus , der als Agent bezeichnet wird. Die Einrichtung eines Agentursystems umfasst drei beteiligte Rollen: reales Objekt (A), Proxy-Objekt (B) und Kunde.
Das Proxy-Objekt (B) spielt eine Vermittlerrolle und verbindet das reale Objekt (A) und den Client. Bei weiterer Erweiterung kann das Proxy-Objekt komplexere Logik implementieren, beispielsweise die Zugriffskontrolle für das reale Objekt Objekt.
Anforderungen: Die Mitarbeiter-Business-Layer-Schnittstelle erfordert eine Administratorberechtigung zum Speichern von Anrufen, und für die Anrufliste ist keine Berechtigung erforderlich, wenn ein Anruf ohne Erlaubnis erfolgt.
/** * 代理接口 */ public interface IEmployeeService { void save(); void list(); }
/** * 真实对象 */ public class EmployeeServiceImpl implements IEmployeeService { @Override public void save() { System.out.println("EmployeeServiceImpl-正常的save...."); } @Override public void list() { System.out.println("EmployeeServiceImpl-正常的list...."); } }
/** * 模拟当前登录用户对象 */ public class SessionHolder { private static String currentUser; public static String getCurrentUser(){ return currentUser; } public static void setCurrentUser(String currentUser){ SessionHolder.currentUser = currentUser; } }
/** * 代理对象 */ public class EmployeeProxy implements IEmployeeService { //真实对象 private EmployeeServiceImpl employeeService; public EmployeeProxy(EmployeeServiceImpl employeeService){ this.employeeService = employeeService; } @Override public void save() { //权限判断 if("admin".equals(SessionHolder.getCurrentUser())){ employeeService.save(); }else{ throw new RuntimeException("当前非admin用户,不能执行save操作"); } } @Override public void list() { employeeService.list(); } }
public class App { public static void main(String[] args) { System.out.println("----------------真实对象--------------------"); EmployeeServiceImpl employeeService = new EmployeeServiceImpl(); employeeService.list(); employeeService.save(); System.out.println("----------------代理对象--------------------"); SessionHolder.setCurrentUser("dafei"); //设置权限(当前登录用户) EmployeeProxy employeeProxy = new EmployeeProxy(employeeService); employeeProxy.list(); employeeProxy.save(); } }
----------------真实对象-------------------- EmployeeServiceImpl-正常的list.... EmployeeServiceImpl-正常的save.... ----------------代理对象-------------------- EmployeeServiceImpl-正常的list.... Exception in thread "main" java.lang.RuntimeException: 当前非admin用户,不能执行save操作 at com.langfeiyes.pattern.proxy.demo.EmployeeProxy.save(EmployeeProxy.java:20) at com.langfeiyes.pattern.proxy.demo.App.main(App.java:16)
Beim direkten Aufruf über das reale Objekt EmployeeServiceImpl kann sowohl auf die Liste als auch auf das Speichern direkt zugegriffen werden, es erfüllt jedoch nicht die Anforderungen an die Administratorberechtigungsbeschränkungen. Wenn Sie das Proxy-Objekt EmployeeProxy verwenden, können Sie die Anforderungen erfüllen.
Vervollständigen Sie die Proxy-Logik, indem Sie direkt eine neue Klasse von Proxy-Objekten erstellen. Diese Methode wird als statischer Proxy-Modus bezeichnet.
Zu den häufig verwendeten dynamischen Proxy-Modi in Java gehören der dynamische JDK-Proxy und der dynamische Cglib-Proxy. Hier konzentrieren wir uns auf den dynamischen JDK-Proxy 🎜#Immer noch die ursprüngliche Anforderung, der vorherige IEmployeeService EmployeeServiceImpl SessionHolder hat sich nicht geändert, ein neuer JDK-Proxy-Controller-EmployeeInvocationHandler
/** * jdk动态代理控制类,由它牵头代理类获取,代理方法的执行 */ public class EmployeeInvocationHandler implements InvocationHandler { //真实对象-EmployeeServiceImpl private Object target; public EmployeeInvocationHandler(Object target){ this.target = target; } //获取jvm在内存中生成代理对象 public Object getProxy(){ return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } //代理对象控制执行方法 //参数1:代理对象 //参数2:真实对象的方法(使用方式得到方法对象) //参数3:真实对象方法参数列表 //此处是代理对象对外暴露的可编辑的方法处理场所,代理对象每调用一个次方法,就会执行一次invoke @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String name = method.getName(); if("save".equals(name) && !"admin".equals(SessionHolder.getCurrentUser())){ throw new RuntimeException("当前非admin用户,不能执行save操作"); } return method.invoke(target, args); } }
# 🎜🎜#
public class App { public static void main(String[] args) { System.out.println("----------------真实对象--------------------"); EmployeeServiceImpl employeeService = new EmployeeServiceImpl(); employeeService.list(); employeeService.save(); System.out.println("----------------代理对象--------------------"); SessionHolder.setCurrentUser("dafei"); EmployeeInvocationHandler handler = new EmployeeInvocationHandler(employeeService); IEmployeeService proxy = (IEmployeeService) handler.getProxy(); proxy.list(); proxy.save(); } }
Teilnehmende Rolle
Um das Prinzip des dynamischen JDK-Proxys zu verstehen, müssen Sie zunächst die am dynamischen JDK-Proxy beteiligten Klassen verstehen#🎜🎜 #
InvocationHandler: Aufrufhandler für echte Objektmethoden, integrierte Aufrufmethode, ihre Funktion: Proxy-Logik für reale Objekte anpassen
#🎜🎜 #EmployeeInvocationHandler#🎜 🎜#: Handler für reale Objektmethoden des Mitarbeiterdienstes. Diese Klasse hat drei Zwecke: 1> Festlegen des realen Objekts //真实对象-EmployeeServiceImpl
private Object target;
public EmployeeInvocationHandler(Object target){
this.target = target;
}
//代理对象控制执行方法 //参数1:代理对象 //参数2:真实对象的方法(使用方式得到方法对象) //参数3:真实对象方法参数列表 //此处是代理对象对外暴露的可编辑的方法处理场所,代理对象每调用一个次方法,就会执行一次invoke @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String name = method.getName(); if("save".equals(name) && !"admin".equals(SessionHolder.getCurrentUser())){ throw new RuntimeException("当前非admin用户,不能执行save操作"); } return method.invoke(target, args); }
//获取jvm在内存中生成代理对象 public Object getProxy(){ return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); }
Proxy
: Die dynamische Proxy-Steuerklasse ist die übergeordnete Klasse der vom JDK dynamisch generierten $ProxyX-Klasse. Ihre Funktion ist wie folgt:1>By Aufruf der ProxyBuilder-Klasse Die Builder-Methode erstellt die Proxy-Objektklasse
private static Constructor<?> getProxyConstructor(Class<?> caller, ClassLoader loader, Class<?>... interfaces){ return proxyCache.sub(intf).computeIfAbsent( loader, (ld, clv) -> new ProxyBuilder(ld, clv.key()).build() ); }
2> gibt eine Instanz der $ProxyX-Klasse über die newProxyInstance-Methode
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) { //... }
: App-Klassenlaufzeit, die vom JDK dynamisch erstellte Proxy-Klasse, geerbt von der Proxy-Klasse public class App {
public static void main(String[] args) {
//System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
System.setProperty("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");
System.out.println("----------------真实对象--------------------");
EmployeeServiceImpl employeeService = new EmployeeServiceImpl();
employeeService.list();
employeeService.save();
System.out.println("----------------代理对象--------------------");
SessionHolder.setCurrentUser("dafei");
EmployeeInvocationHandler handler =
new EmployeeInvocationHandler(employeeService);
IEmployeeService proxy = (IEmployeeService) handler.getProxy();
proxy.list();
proxy.save();
}
}
//JDK8之前 System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); //JDK8之后 System.setProperty("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");
Um die Interpretation zu erleichtern, nach dem Entfernen einiger unnötiger Methoden
$Proxy0-Klasse#🎜🎜 #public class $Proxy0 extends Proxy implements IEmployeeService { private static Method m4; private static Method m3; static { try { m4 = Class.forName("com.langfeiyes.proxy.demo.IEmployeeService") .getMethod("save"); m3 = Class.forName("com.langfeiyes.proxy.demo.IEmployeeService") .getMethod("list"); } catch (Exception e) { e.printStackTrace(); } } public $Proxy0(InvocationHandler var1) throws Throwable { super(var1); } public final void save() throws Throwable { super.h.invoke(this, m4, (Object[])null); } public final void list() throws Throwable{ super.h.invoke(this, m3, (Object[])null); } }
Aus dem Quellcode die Eigenschaften von $Proxy0:
1>Erbt die Proxy-Klasse , implementiert die IEmployeeService-Schnittstelle
2> spiegelt die Speicher- und Listenmethoden der IEmployeeService-Schnittstelle über statische Blöcke wider, um ihre Methodenobjekte abzurufen. Methode
# 🎜🎜#
Das obige ist der detaillierte Inhalt vonSo implementieren Sie den dynamischen JDK-Proxy in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!