Java代理也是Java安全中较为重要且基础的一环,所以进行单独记录。
本文示例大多参考于Drunkbaby师傅,首先膜一下大师傅。
在讲代理之前,先说一下何为代理,通俗的讲解,当我们在购买房子时,我们需要通过中介来进行,即中介从房东手中获取房源,我们通过中介了解到房屋信息,中介起到了一个中间人的作用,此时他相当于代理。
在Java代理中,又具体分为两种,静态代理和动态代理,接下来依次进行查看。
角色分析
抽象角色:一般会用接口或者抽象类来解决
真实角色:被代理的角色
代理角色:代理真实角色,代理真实角色后,一般会做一些附属操作
客户:访问代理对象的人
这里仍以租房为例,首先我们要租房,看到需要有一个租房的接口,也就是官方的抽象角色,其代码如下
#Rent.java
package org.example;
public interface Rent{
public void rent();
}
而后呢,我们这里是房东去出租房屋,所以我们需要房东去调用这个接口并重写方法,这里的房东就是真实角色,其代码如下:
package org.example;
public class Host implements Rent{
public void rent(){
System.out.println("房东要出租房子");
}
}
而后呢,理想的情况下,是我们直接联系到房东,买房子,此时也就是我们调用这个类生成对象,调用租房接口,此时我们就是对应客户,代码如下
package org.example;
public class Client {
public static void main(String[] args){
Host host = new Host();
host.rent();
}
}
此时运行就会发现
成功得到房租要出租房子的信息,也就是我们客户成功对接上了房东,但现实的情况往往是我们联系不到房东,所以这个时候就需要中介了,中介不仅继承了租房接口,同时他会提供一些其他方法,比如,收中介费,签合同等,具体代码如下
#Proxy.java
package org.example;
public class Proxy implements Rent{
private Host host;
public Proxy(){
}
public Proxy(Host host){
this.host=host;
}
public void rent(){
seeHouse();
host.rent();
fare();
hetong();
}
public void seeHouse(){
System.out.println("中介带你看房");
}
public void fare(){
System.out.println("收中介费");
}
public void hetong(){
System.out.println("签合同");
}
}
接下来我们通过客户再次进行调用,不过此次不是直接调用房东,而是通过中介,具体代码如下
#Client.java
package org.example;
public class Client {
public static void main(String[] args){
Host host = new Host();
Proxy proxy =new Proxy(host);
proxy.rent();
}
}
此时即可实现代理
刚刚只有一个接口,接下来我们接近实际,这里设置四个接口,分别用于增删改查,具体代码如下
#UserService.java
package org.example.demo01;
public interface UserService {
public void add();
public void delete();
public void update();
public void query();
}
然后这个是一个抽象类,我们需要有具体实现它的,所以接下来写一个对象来进行调用
#UserServiceimp.java
package org.example.demo01;
public class UserServiceimp 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("查询了一个用户");
}
}
此时有需求如下:我们需要添加一个日志功能,即每次调用方法前,我们需要在方法前输出调用了xxx方法
,这个时候该如何实现呢,方法有两种
1、在每个方法前添加Systme.out.println("调用了xxx方法");
2、添加代理类,对日志进行处理
基于不改动源代码的原则,且由于第一个方法过于繁琐,需要更改多处代码,所以这里选用代理来实现。接下来我们新建一个代理方法
#UserServiceProxy.java
package org.example.demo01;
public class UserServiceProxy implements UserService{
private UserService userService;
public void setUserService(UserServiceimp userService) {
this.userService = userService;
}
@Override
public void add() {
log("add");
userService.add();
}
@Override
public void delete() {
log("delete");
userService.delete();
}
@Override
public void update() {
log("update");
userService.update();
}
@Override
public void query() {
log("query");
userService.query();
}
public void log(String msg){
System.out.println("[Debug]使用了"+msg+"方法");
}
}
接下来再写一个启动器。
#Client.java
package org.example.demo01;
public class Client{
public static void main(String[] args){
UserServiceimp userService = new UserServiceimp();
UserServiceProxy proxy = new UserServiceProxy();
proxy.setUserService(userService);
proxy.add();
proxy.update();
}
}
此时运行即可发现成功添加了日志