Create a protection agent using Java API (Head first design pattern)
Java in Java Lang.reflect package has its own Proxy support. Using this package, we can dynamically create a Proxy class (Proxy) at runtime, implement one or more interfaces, and forward the call of the method to the class that implements the InvocationHandler interface. Because the actual agent class is created at runtime, we call this technology: dynamic agent.
We need to introduce a java proxy to protect the following requirements
Pairing of target villages
Assuming that every town needs matching service, we are responsible for helping the target village implement the dating matching management system. A good idea is to set up the evaluation of "Hot" and "Not", where "Hot" represents like and "Not" represents dislike.
Our service system first involves a Person Bean and creates a Person Bean interface
public interface PersonBean { String getName(); String getGender(); String getInterests(); int getHotOrNotRating(); void setName(String name); void setGender(String gender); void setInterests(String interests); void setHotOrNotRating(int rating); }
Create the PersonBean implementation class PersonBeanImpl
public class PersonBeanImpl implements PersonBean{ String name; String gender; String interests; int rating; int ratingCount = 0; @Override public String getName() { return name; } @Override public String getGender() { return gender; } @Override public String getInterests() { return interests; } @Override public int getHotOrNotRating() { //Calculate your HotOrNotRating average if(ratingCount == 0) return 0; return rating/ratingCount; } @Override public void setName(String name) { this.name = name; } @Override public void setGender(String gender) { this.gender = gender; } @Override public void setInterests(String interests) { this.interests = interests; } @Override public void setHotOrNotRating(int rating) { this.rating += rating; ratingCount++; } }
Here, any user in the system can change other people's data at will. For example, I can modify other people's interests, gender, HotOrNotRating average value and so on at will. This is obviously unsafe, which may cause others to fail to date. Therefore, we need to set the system as the owner (oneself) to modify our own information. Non owners (others) can only affect their HotOrNotRating value. Here we need to use the protection agent - an agent that determines whether customers can access the object according to the access permission
To create this kind of proxy, we must use the dynamic proxy of Java API. java will create two proxies for us. We only need to provide handler to handle the transferred methods.
Step 1: create two invocationhandlers
InvocationHandler implements the behavior of proxy, and java is responsible for creating real proxy classes and objects. We only need to provide a handler that knows what to do when the method is called
Step 2: write code to create a dynamic proxy
We need to write some methods to generate Proxy instances. You'll see it later
Step 3: Test
Step 1: create two invocationhandlers
Whenever the method of the proxy object is called, the invoke() method in the InvocationHandler's implementation class will be called.
Create OwnerInvocationHandler (owner)
public class OwnerInvocationHandler implements InvocationHandler { PersonBean personBean; public OwnerInvocationHandler(PersonBean personBean){ this.personBean = personBean; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("OwnerInvocationHandler->Called invoke method"); try{-u jol,, if(method.getName().startsWith("get")){ return method.invoke(personBean, args); }else if(method.getName().equals("setHotOrNotRating")){ throw new IllegalAccessException(); }else if(method.getName().startsWith("set")){ return method.invoke(personBean, args); } }catch (InvocationTargetException invocationTargetException){ invocationTargetException.printStackTrace(); } return null; } }
Create NonOwnerInvocationHandler (non owner)
public class NonOwnerInvocationHandler implements InvocationHandler { PersonBean personBean; public NonOwnerInvocationHandler(PersonBean personBean){ this.personBean = personBean; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("NonOwnerInvocationHandler->Called invoke method"); try{ if(method.getName().startsWith("get")){ return method.invoke(personBean, args); }else if(method.getName().equals("setHotOrNotRating")){ return method.invoke(personBean, args); }else if(method.getName().startsWith("set")){ throw new IllegalAccessException(); } }catch (InvocationTargetException invocationTargetException){ invocationTargetException.printStackTrace(); } return null; } }
Step 2: write code to create a dynamic proxy
Write methods to get instances of owner and non owner agents
//Get my Proxy instance. Because Proxy and PersonBean implement the same interface, you can directly return the PersonBean object public static PersonBean getOwnerProxy(PersonBean person){ return (PersonBean) Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), new OwnerInvocationHandler(person)); } //Get the non personal Proxy instance. Because Proxy and PersonBean implement the same interface, you can directly return the PersonBean object public static PersonBean getNotOwnerProxy(PersonBean person){ return (PersonBean) Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), new NonOwnerInvocationHandler(person)); } }
Step 3: Test
Create test class
public class Test { public static void main(String[] args) { PersonBean person = new PersonBeanImpl(); PersonBean ownerProxy = getOwnerProxy(person); try { ownerProxy.setHotOrNotRating(100); } catch (Exception e) { System.out.println("You can't set a score for yourself~"); } PersonBean notOwnerProxy = getNotOwnerProxy(person); try{ notOwnerProxy.setGender("male"); } catch (Exception e){ System.out.println("Can't set other people's information~"); } } }
result
You can see that every time we call the method of the PersonBean instance at runtime, we pass the call to the corresponding implementation class that implements the InvocationHandler interface through the Proxy instance. The dynamic agent is realized. In the corresponding invoke() method, certain permission control is also carried out to control the access to the method, and the protection agent is preliminarily realized.