定义:Provide a surrogate or placeholder for another object to control access to it;
为其他对象提供一种代理以控制对这个对象的访问。
普通代理模式:要求客户端只能访问代理角色,不能访问实际角色。
基础接口类:
package com.kaisen.mainland.Text;
/**
* @author huzhibo
* @Description: 程序员
* @date 2020/9/6 16:59
*/
public interface Programmer {
/**
* 打开电脑
*/
public void turnOnComputer();
/**
* 用户名密码进入
*/
public void loginComputer(String username ,String password);
/**
* 开始工作
* @param work 工作内容
*/
public void doSomeThing(String work);
/**
* 关机
*/
void turnOffComputer();
}
基础实现类:
package com.kaisen.mainland.Text;
/**
* @author huzhibo
* @Description: 程序员的普通代理实际实现类
* @date 2020/9/6 17:02
*/
public class IProgrammer implements Programmer {
private String name = "";
/**
* 构造函数
*/
public IProgrammer(Programmer programmer,String name ){
if (programmer == null){
System.out.println("不能创建真实角色");
}else {
this.name = name;
}
}
@Override
public void turnOnComputer() {
System.out.println("打开电脑");
}
@Override
public void loginComputer(String username ,String password) {
System.out.println("用户名密码登陆上用户名:"+username+" 密码:"+password);
}
@Override
public void doSomeThing(String work) {
System.out.println("我开始工作了"+work);
}
@Override
public void turnOffComputer() {
System.out.println("工作结束了,我关了电脑");
}
}
代理类:
package com.kaisen.mainland.Text;
/**
* @author huzhibo
* @Description: 程序员代理类
* @date 2020/9/6 17:07
*/
public class ProgrammerProxy implements Programmer {
private Programmer programmer = null;
/**
* 通过构造函数限制类的创建
* @param name
*/
public ProgrammerProxy(String name){
programmer = new IProgrammer(this,name);
}
@Override
public void turnOnComputer() {
this.programmer.turnOnComputer();
}
@Override
public void loginComputer(String username, String password) {
this.programmer.loginComputer(username,password);
}
@Override
public void doSomeThing(String work) {
this.programmer.doSomeThing(work);
}
@Override
public void turnOffComputer() {
this.turnOnComputer();
}
}
业务场景类:
package com.kaisen.mainland.Text;
/**
* @author huzhibo
* @Description: 场景类
* @date 2020/9/6 17:14
*/
public class Client {
public static void main(String[] args) {
ProgrammerProxy hu = new ProgrammerProxy("胡旺旺");
System.out.println("上班实际:09:00");
hu.turnOnComputer();
hu.loginComputer("huzhibo","hzb123456");
hu.doSomeThing("敲代码");
hu.turnOffComputer();
}
}
静态代理说完了,那有静态就有动态,那么动态代理是什么呢。
动态代理是实现阶段不需要关心代理谁。而在运行阶段才指定代理哪一个对象,也就是需要手写代理类叫做静态代理,java的AOP核心就是使用了动态代理,那我们先看一组代码来理解动态代理的实现方式。
刚我们手动创建了一个代理类ProgrammerProxy,如果每个类都有自己的代理,那么业务代码会很复杂。因此我们能不能写一个没有属性的代理类呢,只有在调用的时候赋给他哪个对象,他就是哪个对象的代理。
我们首先修改实现接口类:
package com.kaisen.mainland.Text;
/**
* @author huzhibo
* @Description: 程序员的普通代理实际实现类
* @date 2020/9/6 17:02
*/
public class IProgrammer implements Programmer {
private String name = "";
/**
* 构造函数
*/
public IProgrammer(String name ){
this.name = name;
}
@Override
public void turnOnComputer() {
System.out.println("打开电脑");
}
@Override
public void loginComputer(String username ,String password) {
System.out.println("用户名密码登陆上用户名:"+username+" 密码:"+password);
}
@Override
public void doSomeThing(String work) {
System.out.println("我开始工作了"+work);
}
@Override
public void turnOffComputer() {
System.out.println("工作结束了,我关了电脑");
}
}
动态代理如下:
package com.kaisen.mainland.Text;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @author huzhibo
* @Description: 动态代理
* @date 2020/9/6 17:26
*/
public class ProgrammerIH implements InvocationHandler {
//被代理者
// class cls = null;
//被代理实例
Object obj = null;
public ProgrammerIH(Object obj){
this.obj= obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = method.invoke(this.obj, args);
return invoke;
}
}
业务代码如下:
package com.kaisen.mainland.Text;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* @author huzhibo
* @Description: 场景类
* @date 2020/9/6 17:14
*/
public class Client {
public static void main(String[] args) {
IProgrammer hu = new IProgrammer("胡旺旺");
InvocationHandler huHandler = new ProgrammerIH(hu);
System.out.println("上班实际:09:00");
ClassLoader classLoader = hu.getClass().getClassLoader();
Programmer Programmer = (Programmer)Proxy.newProxyInstance(classLoader, new Class[]{Programmer.class}, huHandler);
Programmer.turnOnComputer();
Programmer.loginComputer("huzhibo","hzb123456");
Programmer.doSomeThing("敲代码");
Programmer.turnOffComputer();
}
}
好了,其实到这块动态代理已经说完了,但是还是还是觉得有点奇怪,为什么要使用动态代理呢,我们直接调用接口类就可以了啊,那么现在需求发生变化了,需要我们记录每个客户调用的动作日志呢。我们如果直接使用接口调用需要修改从基础类到业务类所有的代码,这个肯定让我们不开心了,那如果使用代理类我们应该怎么使用呢?
好,先增加一个通知的接口及通知的实现:
package com.kaisen.mainland.Text;
/**
* @author huzhibo
* @Description: 通知
* @date 2020/9/6 17:44
*/
public interface IAdvice {
public void welcomeMessage();
}
class BeforeAdvice implements IAdvice{
@Override
public void welcomeMessage() {
System.out.println("打印日志");
}
}
再修改代理类重的代码:
package com.kaisen.mainland.Text;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @author huzhibo
* @Description: 动态代理
* @date 2020/9/6 17:26
*/
public class ProgrammerIH implements InvocationHandler {
//被代理者
// class cls = null;
//被代理实例
Object obj = null;
public ProgrammerIH(Object obj){
this.obj= obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = method.invoke(this.obj, args);
new BeforeAdvice().welcomeMessage();
return invoke;
}
}
好了,不用修改业务代码及底层的逻辑代码即可实现我们需要的功能,是不是很友好呢。
思考:AOP实现原理