Jdk 动态代理(一个实际案例使用)

来源:互联网 发布:实用五金工具手册软件 编辑:程序博客网 时间:2024/06/15 21:04

Jdk 动态代理:利用java的反射,允许运行时动态地创建一个代理类,实现一个或多个接口,将方法的调用转发到你所指定的类。

 

问题场景:

有一个Person类,其中属性字段有:姓名name、性别gender、兴趣interests、评分值hotOrNotRating,要求:get方法所有字段,对于所有该类实例拥有者或者非该类实例拥有者都有效,而该类实例拥有者除了不能给自己评分之外,可以修改所有的其他字段,而非该类实例拥有者只能设置该评分值,而不能修改其他所有的字段。

 

利用Java动态代理实现代码如下:

PersonBean.java 类如下:

public interface PersonBean {    String getName(); // 取得人的名字    String getGender(); // 性别    String getInterests(); // 兴趣    int getHotOrNotRating(); // HotOrNot评分(1到10)    void setName(String name);    void setGender(String name);    void setInterests(String interests);    void setHotOrNotRating(int rating);}

PersonBeanImpl.java 类如下:

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() {        if (ratingCount == 0) return 0;        return (rating/ratingCount);    }    @Override    public void setName(String name) {        this.name = name;    }    @Override    public void setGender(String name) {        this.gender = gender;    }    @Override    public void setInterests(String interests) {        this.interests = interests;    }    @Override    public void setHotOrNotRating(int rating) {        this.rating += rating;        ratingCount++;    }}

拥有者使用类的情况:

OwnerInvocationHandler.java 类如下:

** *  拥有者使用类的情况 */public class OwnerInvocationHandler implements InvocationHandler {    PersonBean person;    public OwnerInvocationHandler(PersonBean person){        this.person = person;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException {        try {            if (method.getName().startsWith("get")){                return method.invoke(person, args);            } else if (method.getName().equals("setHotOrNotRating")) {                throw new IllegalAccessException();            } else if (method.getName().startsWith("set")) {                return method.invoke(person, args);            }        } catch (InvocationTargetException e) { // 真正主题抛出异常            e.printStackTrace();        }        return null; // 如果调用其他的方法,一律不理,返回null    }}

非拥有者使用类如下:

NonOwnerInvocationHandler.java 类如下:

public class NonOwnerInvocationHandler implements InvocationHandler {    PersonBean person;    public NonOwnerInvocationHandler(PersonBean person) {        this.person = person;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException {        try {            if (method.getName().startsWith("get")){                return method.invoke(person, args);            } else if (method.getName().equals("setHotOrNotRating")) {                return method.invoke(person, args);            } else if (method.getName().startsWith("set")) {                throw  new IllegalAccessException();            }        } catch (InvocationTargetException e) { // 真正主题抛出异常            e.printStackTrace();        }        return null; // 如果调用其他的方法,一律不理,返回null    }}

测试类如下:

MatchMakikngTestDrive.java 类:

public class MatchMakingTestDrive {    public static void main(String[] args) {        MatchMakingTestDrive test = new MatchMakingTestDrive();        test.drive();    }    public void drive() {        PersonBean joe = new PersonBeanImpl();        joe.setName("tim"); joe.setGender("girl"); joe.setInterests("watch movies"); joe.setHotOrNotRating(0);        PersonBean ownerProxy = getOwnerProxy(joe);        System.out.println("Name is: " + ownerProxy.getName());        ownerProxy.setInterests("bowling, Go");        System.out.println("Interests set from owner proxy");        try {            ownerProxy.setHotOrNotRating(10);        } catch (Exception e) {            System.out.println("Can't set rating from owner proxy");        }        System.out.println("Rating is " + ownerProxy.getHotOrNotRating());        PersonBean nonOwnerProxy = getNonOwnerProxy(joe);        System.out.println("Name is: " + nonOwnerProxy.getName());        try {            nonOwnerProxy.setInterests("bowling, go");        } catch (Exception e) {            System.out.println("Can't set interests from non owner proxy");        }        nonOwnerProxy.setHotOrNotRating(3);        System.out.println("Rating set from non owner proxy");        System.out.println("Rating is " + nonOwnerProxy.getHotOrNotRating());    }    PersonBean getOwnerProxy(PersonBean person) {        return (PersonBean) Proxy.newProxyInstance(person.getClass().getClassLoader(),                person.getClass().getInterfaces(),                new OwnerInvocationHandler(person));    }    PersonBean getNonOwnerProxy(PersonBean person) {        return (PersonBean) Proxy.newProxyInstance(person.getClass().getClassLoader(),                person.getClass().getInterfaces(),                new NonOwnerInvocationHandler(person));    }}

输出:

Name is: tim

Interests setfrom owner proxy

Can't setrating from owner proxy

Rating is 0

Name is: tim

Can't setinterests from non owner proxy

Rating setfrom non owner proxy

Rating is 1

 

分析:

需要实现InvocationHandler接口,然后会自动覆盖如下方法:

public Object invoke(Object proxy,Method method, Object[] args)throws IllegalAccessException

在实现类中需要传入需要代理的类字段

在invoke方法中进行调用。

返回该类的实例:

return (PersonBean) Proxy.newProxyInstance(person.getClass().getClassLoader(),
               person.getClass().getInterfaces(),
                new OwnerInvocationHandler(person));











原创粉丝点击