动态代理:运行时动态地创建代理类对象,并将方法调用转发到指定类。
创建过程时动态的,代理类对象具体对主对象管理和控制访问方法对时候也是动态地指定的,方法的控制管理也是动态的。
比如Proxy可以直接拿出一个对象来,Proxy和InvocationHandler组合成代理的角色或者是替身的角色。实际对象RealSubject它提供的功能是有个接口的实现(接口是Subject),User访问之前不想直接访问RealSubject,而是用动态代理代替访问,动态地产生,动态代理可以不止一个。有些控制得多,有些控制得少。不同的用户也可以用不同的代理,接入到真实的类RealSubject。其中,可以说Proxy实现了Subject接口,从用户的角色看,User调用Proxy的时候,User调用的方法是跟RealSubject的方法是一样的。但是这些方法能不能调用成功,或者能不能得到最终的结果,就是对实际对象RealSubject实际的访问控制和管理,是由InvocationHandler的逻辑程序方法invoke()管理控制的。而管理控制的过程正好是保护代理的角色。
动态代理源代码
:
MainTest.java
:
public class MainTest {
public static void main(String[] args) {
MatchService mMatchService=new MatchService();
}
}
MatchService.java
:
import java.lang.reflect.Proxy;
/**
* 匹配服务
* InvocationHandler和Proxy合作
*/
public class MatchService {
public MatchService() {
PersonBean joe = getPersonInfo("joe", "male", "running");
PersonBean ownerProxy = getOwnerProxy(joe);
System.out.println("本人是Name is " + ownerProxy.getName());
System.out.println("Interests is " + ownerProxy.getInterests());
ownerProxy.setInterests("新的兴趣爱好");
System.out.println("Interests are " + ownerProxy.getInterests());
ownerProxy.setHotOrNotRating(50);
System.out.println("Rating is " + ownerProxy.getHotOrNotRating());
ownerProxy.setHotOrNotRating(40);
System.out.println("Rating is " + ownerProxy.getHotOrNotRating());
System.out.println("**************");
PersonBean nonownerProxy = getNonownerProxy(joe);
System.out.println("非本人Name is " + nonownerProxy.getName());
System.out.println("Interests are " + nonownerProxy.getInterests());
nonownerProxy.setInterests("haha");
System.out.println("Interests are " + nonownerProxy.getInterests());
nonownerProxy.setHotOrNotRating(60);
System.out.println("Rating is " + nonownerProxy.getHotOrNotRating());
}
PersonBean getPersonInfo(String name, String gender, String interests) {
PersonBean person = new PersonBeanImpl();
person.setName(name);
person.setGender(gender);
person.setInterests(interests);
return person;
}
/**
* 动态产生代理,Proxy是Java自带的服务
*/
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));
}
}
NonOwnerInvocationHandler.java
:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 非用户本人访问控制
*/
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 Throwable {
if (method.getName().startsWith("get")) // 查看,全部放行
{
return method.invoke(person,args);
}
if (method.getName().equals("setHotOrNotRating")) // 打分,放行
{
return method.invoke(person,args);
}
if (method.getName().startsWith("set")) // 填写,拦截
{
return new IllegalAccessException();
}
return null;
}
}
OwnerInvocationHandler.java
:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 对作者本人对访问权限控制
*/
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 Throwable {
// 实现对对象的访问控制
if(method.getName().startsWith("get")) // 如果是getXX方法,就全部放行
{
return method.invoke(person,args);
}
if (method.getName().equals("setHotOrNotRating")) // 设置评分,拦截
{
return new IllegalAccessException(); // 非法权限接入异常
}
if (method.getName().startsWith("set")) // 填写兴趣爱好,放行
{
return method.invoke(person,args);
}
return null;
}
}
PersonBean接口
:
/**
* Subject接口
*/
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);
}
PersonBeanImpl.java
:
/**
* RealSubject接口
*/
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 gender) {
this.gender=gender;
}
@Override
public void setInterests(String interests) {
this.interests=interests;
}
@Override
public void setHotOrNotRating(int rating) {
this.rating=rating;
ratingcount++;
}
}
运行结果
:
几种常见的代理模式介绍— 几种变体
- 防火墙代理
- 缓存代理
Android端访问物联网图片慢加载的时候,把之前在本地缓存过的图片拿出来。 - 智能引用代理
做辅助工作 - 同步代理
在多线程操作操作过程中,进行多线程之间进行同步访问对象 - 写入时复制代理
复制东西实际上不操作,在真正写入的时候,复制的工作才做起来
代理模式关键点
代理模式原理和意义
Java RMI关键点
代理模式和装饰者模式差异
代理模式关键点— 代理模式原理和意义
代理模式原理的推导过程
类图结构
代理模式关键点— Java RMI关键点
记住4个制作步骤:
制作远程接口:接口文件
远程接口的实现:Service文件
RMI服务端注册,开启服务
RMI代理端通过RMI查询到服务端,建立联系,通过接口调用远程方法
代理模式关键点— 代理模式和装饰者模式差异
装饰者模式,装饰以后会添加新功能
代理模式目的是对目标对象访问的控制和管理
本文改编自极客学院官网视频