11.代理模式
静态代理
角色分析
-
抽象角色 : 一般使用抽象类或者接口实现,体现一个动作
-
真实角色 : 被代理的角色
-
代理角色 : 代理真实角色 , 并且能够在基础动作上进行附加操作
-
客户 : 访问代理对象
//抽象角色 public class StaticProxy { public static void main(String[] args) { GotoSchoolHelper gotoSchoolHelper = new GotoSchoolHelper(new You()); gotoSchoolHelper.goToSchool(); } } interface GoToSchool{ void goToSchool(); } //真实角色 class You implements GoToSchool{ @Override public void goToSchool() { System.out.println("张三去上学了"); } } //代理角色 class GotoSchoolHelper implements GoToSchool{ private GoToSchool people; public GotoSchoolHelper(GoToSchool target) { this.people= target; } @Override public void goToSchool() { before(); //前附属操作 this.people.goToSchool(); after(); //后附属操作 } private void before() { System.out.println("上学之前,吃早饭"); } private void after(){ System.out.println("上学之后,放学"); } }
代理模式的优势
- 可以使得真实角色的操作更加纯粹 , 只需要完成自己的业务就行
- 公共业务可以交给代理角色 , 实现了业务的分工
- 公共业务发生拓展的时候 ,方便集中管理 。 (在代理角色管理即可)
缺点
一个真实角色对应一个代理角色 , 代码量较大,降低了开发效率
业务代码示例
//抽象对象
public interface UserService {
void add();
void delete();
void update();
void query();
}
//实现类 真实对象
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("增加了一个用户");
}
@Override
public void delete() {
System.out.println("删除了一个用户");
}
@Override
public void update() {
System.out.println("修改了一个用户");
}
@Override
public void query() {
System.out.println("查询用户");
}
}
//代理角色 完成了额外的功能
public class UserServiceProxy {
private UserServiceImpl userService;
public void setUserService(UserServiceImpl userService) {
this.userService = userService;
}
public void add() {
newFunction();
this.userService.add();
}
public void update() {
newFunction();
this.userService.update();
}
public void query() {
newFunction();
this.userService.query();
}
public void newFunction() {
System.out.println("这是个附加功能");
}
}
//测试类
public class Test {
@org.junit.Test
public void test() {
UserServiceImpl userService = new UserServiceImpl();
UserServiceProxy proxy = new UserServiceProxy();
proxy.setUserService(userService);
proxy.add();
}
}
AOP面向切面的开发
动态代理模式
解决了静态代理的缺点 , 可以动态生成类
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的 , 不是预先编码好的
- 动态代理分为两大类 :
- 基于接口的动态代理 : JDK动态代理
- 基于类的动态代理 : cglib
- Java字节码实现 : javasist
实现类 Proxy、InvocationHandler
//抽象接口
public interface Rent {
void rent()
}
//房东 真实角色
public class Host implements Rent{
@Override
public void rent() {
System.out.println("我要出租房子");
}
}
动态代理类生成类
//这个类来自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Rent rent ;
public void setRent(Rent rent) {
this.rent = rent; //注入被代理的真实角色
}
public Object getProxy() { //返回真实角色的代理角色w
return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(),this);
}
//处理代理示例并返回结果
@Override //实现真实角色需求同时实现新增需求
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//反射机制实现动态代理
newFunciton();
return method.invoke(rent,args);
}
public void newFunciton() {
System.out.println("一个新的方法");
}
}
public class Test {
@org.junit.Test
public void test() {
//真实角色
Rent rent = new Host();
//代理角色 : 现在还没有 现在是代理角色配置类
ProxyInvocationHandler p = new ProxyInvocationHandler();
//设置代理角色的代理对象
p.setRent(rent); //代理角色注入真实角色
Rent proxy = (Rent) p.getProxy(); //获得代理角色
//代理类实现真实对象方法 , 同时实现自己的附加方法
proxy.rent();
}
}
通用代理配置类
//这个类来自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Object targetInterface;
public void setTargetInterface(Object targetInterface) {
this.targetInterface = targetInterface;
}
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(),targetInterface.getClass().getInterfaces(),this);
}
//处理代理示例并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//反射机制实现动态代理
newFunciton();
return method.invoke( targetInterface,args);
}
public void newFunciton() {
//需要额外实现的方法
}
}
动态代理的好处
- 一个动态代理类可以代理多个类,只要是实现了同一个接口即可
- 克服了静态代理的缺点