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 :

