场景:不直接访问某个对象时,可设置一个代理对象来间接访问,为了保证代码的透明度,委托对象与代理对象需要实现相同的接口。
静态代理和动态代理;代理类和被代理类都要继承或实现相同的接口或方法;代理类通过被代理类的引用来调用具体的业务逻辑。
Retrofit的create就是使用的动态代理模式。
具体实现
功能接口
interface Person {
void say();
void func();
}
被代理类
class XiaoMing implements Person {
@Override
public void say() {
System.out.println("小明");
}
@Override
public void func() {
System.out.println("我会跑步");
}
}
class XiaoLi implements Person {
@Override
public void say() {
System.out.println("小李");
}
@Override
public void func() {
System.out.println("我会唱歌");
}
}
class XiaoWang implements Person {
@Override
public void say() {
System.out.println("小王");
}
@Override
public void func() {
System.out.println("我会游泳");
}
}
使用静态代理的方式
(1)实例化代理对象传入代理类
//代理类
public class PersonProxy implements Person {
private Person person;
public PersonProxy (Person person) {
this.person = person;
}
//更改代理对象
public void setPerson(Person person) {
this.person = person;
}
@Override
public void say() {
if(person != null){
person.say();
}
}
@Override
public void func() {
if(person != null){
person.func();
}
}
}
//使用
PersonProxy proxy = new PersonProxy(new XiaoLi());
proxy.say();
proxy.func();
proxy.setPerson(new XiaoWang());
proxy.say();
proxy.func();
//输出
小李
我会唱歌
小王
我会游泳
(2)利用java反射创建被代理类对象
//代理类
public class PersonProxy implements Person {
private Person person;
//传入被代理类的全类名
public PersonProxy(String clsStr) {
try {
this.person = (Person) Class.forName(clsStr).newInstance();
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
}
//传入被代理类
public PersonProxy(Class<? extends Person> cls) {
try {
this.person = cls.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
@Override
public void say() {
if(person != null) {
person.say();
}
}
@Override
public void func() {
if(person != null) {
person.func();
}
}
}
//使用
PersonProxy proxy1 = new PersonProxy(XiaoMing.class);
proxy1.say();
proxy1.func();
//我这里XiaoWang的JavaBean放在com.demo.test目录下
PersonProxy proxy2 = new PersonProxy("com.demo.test.XiaoWang");
proxy2.say();
proxy2.func();
//输出
System.out: 小明
System.out: 我会跑步
System.out: 小王
System.out: 我会游泳
(3)使用注解指明代理对象
public static final int XIAOMING = 1;
public static final int XIAOLI = 2;
public static final int XIAOWANG = 3;
@Retention(RetentionPolicy.SOURCE)
@IntDef({XIAOMING, XIAOLI, XIAOWANG})
public @interface PersonAnno {}
//代理类
public class PersonProxy implements Person {
private Person person;
//通过注解来指定代理对象
public PersonProxy (@PersonAnno int type) {
if (type == 1) {
person = new XiaoMing();
} else if (type == 2) {
person= new XiaoLi();
} else {
person= new XiaoWang();
}
}
@Override
public void say() {
if(person != null){
person.say();
}
}
@Override
public void func() {
if(person != null){
person.func();
}
}
}
//使用
PersonProxy proxy = new PersonProxy(XIAOMING);
proxy.say();
proxy.func();
//输出
System.out: 小明
System.out: 我会跑步
使用动态代理的方式
(1)传入被代理类的实例化对象
//动态代理类
public class PersonProxy implements InvocationHandler {
Object object;
public PersonProxy(Object object){
this.object = object;
}
public void setObject(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(object.getClass().getSimpleName() + "的" + method.getName() + "调用前");
method.invoke(object, args);//代理类方法调用时的切面
System.out.println(object.getClass().getSimpleName() + "的" + method.getName() + "调用后");
return null;
}
}
//使用
Person xiaoMing = new XiaoMing();
PersonProxy proxy = new PersonProxy(xiaoMing);
Person person = (Person) Proxy.newProxyInstance(xiaoMing.getClass().getClassLoader(), xiaoMing.getClass().getInterfaces(), proxy);
person.say();
person.func();
System.out.println("--------------------------------");
Person xiaoLi = new XiaoLi();
proxy.setObject(xiaoLi);
Person person2 = (Person) Proxy.newProxyInstance(xiaoLi.getClass().getClassLoader(), xiaoLi.getClass().getInterfaces(), proxy);
person2.say();
person2.func();
//输出
System.out: XiaoMing的say调用前
System.out: 小明
System.out: XiaoMing的say调用后
System.out: XiaoMing的func调用前
System.out: 我会跑步
System.out: XiaoMing的func调用后
System.out: --------------------------------
System.out: XiaoLi的say调用前
System.out: 小李
System.out: XiaoLi的say调用后
System.out: XiaoLi的func调用前
System.out: 我会唱歌
System.out: XiaoLi的func调用后
(2)传入被代理类
public class PersonProxy implements InvocationHandler {
Person person;
public PersonProxy(Class<? extends Person> cls){
try {
this.person = cls.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(person.getClass().getSimpleName() + "的" + method.getName() + "调用前");
method.invoke(person, args);//代理类方法调用时的切面
System.out.println(person.getClass().getSimpleName() + "的" + method.getName() + "调用后");
return null;
}
}
//使用
Class cls = XiaoMing.class;
PersonProxy proxy = new PersonProxy(cls);
Person person = (Person) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), proxy);
person.say();
person.func();
//输出
System.out: XiaoMing的say调用前
System.out: 小明
System.out: XiaoMing的say调用后
System.out: XiaoMing的func调用前
System.out: 我会跑步
System.out: XiaoMing的func调用后