Lets look at the what Dynamic Proxy Design Pattern does for us :
Program to demonstrate how to implement Dynamic Proxy Design Pattern in Java.
Click here to download complete source code
Step 1: Creation of Interface
package com.hubberspot.designpatterns.proxy.example; // Create a interface Developer having // few getters and setters. See below ... public interface Developer { String getName(); String getSalary(); String getRole(); int getRating(); void setName(String name); void setSalary(String salary); void setRole(String role); void setRating(int rating); }
Step 2 : Creation of Implementation class
package com.hubberspot.designpatterns.proxy.example; public class DeveloperImpl implements Developer { // Few properties and respective // getters and setters in the // interface String name; String salary; int rating; String role; @Override public String getName() { return name; } @Override public String getSalary() { return salary; } @Override public String getRole() { return role; } @Override public int getRating() { return rating; } @Override public void setName(String name) { this.name = name; } @Override public void setSalary(String salary) { this.salary = salary; } @Override public void setRole(String role) { this.role = role; } @Override public void setRating(int rating) { this.rating = rating; } }
Step 3 : Creation of Dynamic proxie as Developer Invocation Handler
package com.hubberspot.designpatterns.proxy.example; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; // Make a proxie as how methods on Developer calls as per the // developer. public class DeveloperHandling implements InvocationHandler { // having Developer as a instance variable Developer employee; // Constructor of class setting the value of the // Developer instance variable public DeveloperHandling(Developer employee) { this.employee = employee; } // InvocationHandler interface has a method by name // invoke which returns back an Object. It works on // the principle of reflection. Each time a call is // made by Developer on its setter and getter this // method will be called first. // This method takes in three arguments : // 1. Dynamically created proxy object // 2. Method and information regarding the method which // needs to be called. // 3. Plus what arguments called method takes to fulfil // the calling process. @Override public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException { try { // Method class has a method by getName() , which returns // back the method name which is called by the Developer. if(method.getName().startsWith("get")) { // Method class has a method by name invoke(). // This method invokes employee methods and passing // the aruments to it, based on the if condition. return method.invoke(employee, args); } // In order to set restriction on developer to // not able to change state of role, salary and rating // if condition on fulfillment throws IllegalAccessException // because a developer has no right to set his salary, // role and rate himself. It is duty of his manager to // which he reports else if (method.getName().equals("setRole")) { throw new IllegalAccessException(); } else if (method.getName().equals("setSalary")) { throw new IllegalAccessException(); } else if (method.getName().equals("setRating")) { throw new IllegalAccessException(); } } catch(InvocationTargetException e) { e.printStackTrace(); } return null; } }
Step 4 : Creation of Dynamic proxie as Managers Invocation Handler
package com.hubberspot.designpatterns.proxy.example; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; // same explanation as given in DeveloperHandling.java class // above public class ManagersHandling implements InvocationHandler { Developer employee; public ManagersHandling(Developer employee) { this.employee = employee; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException { try { if(method.getName().startsWith("get")) { return method.invoke(employee, args); } else if(method.getName().startsWith("setName")) { throw new IllegalAccessException(); } else if(method.getName().startsWith("set")) { return method.invoke(employee, args); } } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } }
Step 5: Test class for creating Dynamic Proxies and running the code.
package com.hubberspot.designpatterns.proxy.example; import java.lang.reflect.Proxy; import java.util.HashMap; public class HRMTest { // Create a HashMap to store employee object as a // name value pair HashMap developer = new HashMap(); public HRMTest() { // Constructor creates a new Developer by // giving it a few properties. Developer dinesh = new DeveloperImpl(); dinesh.setName("Dinesh Varyani"); dinesh.setSalary("25000"); dinesh.setRating(7); dinesh.setRole("Senior Developer"); developer.put("Dinesh", dinesh); } public static void main(String[] args) { // main method after creating HRMTest object // calls test() method. HRMTest hrmTest = new HRMTest(); hrmTest.test(); } public void test() { // Initially if Proxy Design Pattern hadn't been implemented Developer // and Manager can all change state of Developer/employee properties. System.out.println("---------------------------------------------------"); System.out.println("Let's test Developer perspective .....\n"); // Lets look at developer perspective what he has restriction // on him after implementing Proxy Design pattern. Developer dinesh = (Developer)developer.get("Dinesh"); Developer developerProxy = getDeveloperProxy(dinesh); System.out.println("Name of the developer : " + developerProxy.getName()); // He cannot set his rating, salary and role. An exception will be // thrown which will print following message in sysouts try{ developerProxy.setRating(10); } catch(Exception e) { System.out.println("Developer cant provide rating to itself"); } try{ developerProxy.setSalary("100000"); } catch(Exception e) { System.out.println("Developer increase or set salary to itself"); } try{ developerProxy.setRole("Manager"); } catch(Exception e) { System.out.println("Developer cannot change its role in company\n"); } System.out.println("---------------------------------------------------"); System.out.println("Let's test Managers perspective .....\n"); // Lets look at the Managers perspective now as what it does to developer // object dinesh = (Developer)developer.get("Dinesh"); Developer managerProxy = getManagerProxy(dinesh); System.out.println("Name of the developer : " + managerProxy.getName()); System.out.println("Set salary of the employee : "); managerProxy.setSalary("15000"); System.out.println("Salary of the developer : " + managerProxy.getSalary()); // He cannot change the name of the developer. Rest he can change i.e // salary, role and rating. try{ managerProxy.setName("Mangesh Virani"); } catch(Exception e) { System.out.println("Manager cant change or set name of developer"); } System.out.println("---------------------------------------------------"); } // In order to create Dynamic Proxy we have to apply following steps // in java // This method takes in a Developer object (real) and returns // back the proxy for it. It returns a Developer which acts as // proxy. public Developer getDeveloperProxy(Developer employee) { // To create a Dynamic Proxy we have to call // newProxyInstance() static method of class Proxy. // It takes three arguments : // 1. Class Loader for our real object. // 2. Set of interfaces proxy needs to implement. // 3. A new object of our DeveloperHandling invocation // handler. It takes in the real object and returns // us back with proxy object. return (Developer) Proxy.newProxyInstance( employee.getClass().getClassLoader(), employee.getClass().getInterfaces(), new DeveloperHandling(employee)); } public Developer getManagerProxy(Developer employee) { // Same as above. Instead of Developer now it returns // an proxy on Managers Handling mechanism. return (Developer) Proxy.newProxyInstance( employee.getClass().getClassLoader(), employee.getClass().getInterfaces(), new ManagersHandling(employee)); } }
Click here to download complete source code
Output of the program :