目录
1.代理模式
- Java动态代理与设计模式中的代理模式有关,什么是代理模式呢?
代理模式:给某一个对象提供一个代理,并由代理对象来控制对真实对象的访问。代理模式是一种结构型设计模式。
- 代理模式有什么用?
作用:通过代理可以控制访问某个对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理。(即: AOP的微观实现!)
- 核心角色
-
抽象角色(接口):定义公共对外方法
-
真实角色(周杰伦):实现抽象角色,定义真实角色所要实现的业务逻辑,
-
代理角色(代理人):实现抽象角色,是真实角色的代理,通过调用真实角色的方法来完成业务逻辑,并可以附加自己的操作
2.静态代理
先通过实例来学习静态代理,然后理解静态代理的缺点,再来学习本文主角:动态代理
编写一个接口 Star ,以及该接口的一个实现类 RealStar
- 抽象角色:Star接口
public interface Star {
/**
* 面谈
*/
void confer();
/**
* 签合同
*/
void signContract();
/**
* 订票
*/
void bookTicket();
/**
* 唱歌
*/
void sing();
/**
* 收钱
*/
void collectMoney();
}
- 真实角色:RealStar实现类
public class RealStar implements Star {
public void bookTicket() {
}
public void collectMoney() {
}
public void confer() {
}
public void signContract() {
}
public void sing() {
System.out.println("周杰伦:唱兰亭序");
}
}
- 代理角色:ProxyStar
public class ProxyStar implements Star {
private Star star;
public ProxyStar(Star star) {
super();
this.star = star;
}
public void bookTicket() {
System.out.println("经纪人:定机票");
}
public void collectMoney() {
System.out.println("经纪人:收尾款");
}
public void confer() {
System.out.println("经纪人:面谈");
}
public void signContract() {
System.out.println("经纪人:签合同");
}
public void sing() {
star.sing();
}
}
- 客户端测试
public class Client {
public static void main(String[] args) {
Star proxy = new ProxyStar(new RealStar());
proxy.confer();
proxy.signContract();
proxy.bookTicket();
proxy.sing();
proxy.collectMoney();
}
}
- 运行结果
经纪人:面谈
经纪人:签合同
经纪人:定机票
周杰伦:唱兰亭序
经纪人:收尾款
- 静态代理优缺点
通过静态代理,我们达到了功能增强的目的,而且没有侵入原代码,这是静态代理的一个优点。
虽然静态代理实现简单,且不侵入原代码,但是,当场景稍微复杂一些的时候,静态代理的缺点也会暴露出来。
-
当需要代理多个类的时候,由于代理对象要实现与目标对象一致的接口,有两种方式:
- 只维护一个代理类,由这个代理类实现多个接口,但是这样就导致代理类过于庞大
- 新建多个代理类,每个目标对象对应一个代理类,但是这样会产生过多的代理类
-
当接口需要增加、删除、修改方法的时候,实现类与代理类都要同时修改,不易维护。
-
代理类和实现类实现了相同的接口,这样就出现了大量的代码重复。
3.动态代理
3.1 JDK动态代理
- 抽象接口:star接口
public interface Star {
/**
* 唱歌
*/
void sing();
}
- 真实角色:RealStar实现类
public class RealStar implements Star {
public void sing() {
System.out.println("周杰伦:唱青花瓷");
}
}
- 代理工厂:
public class ProxyFactory {
// 被代理的对象,实际的方法执行者(周杰伦)
private Object star;
public ProxyFactory(Object star) {
this.star = star;
}
public Object getProxyObject(){
//返回一个代理对象
return Proxy.newProxyInstance(star.getClass().getClassLoader(),
star.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("经纪人:面谈");
System.out.println("经纪人:签合同");
System.out.println("经纪人:定机票");
// 调用 周杰伦 的 method 方法
Object invoke = method.invoke(star, args);
System.out.println("经纪人:收尾款");
// 返回方法的执行结果
return invoke;
}
});
}
}
- 运行结果
经纪人:面谈
经纪人:签合同
经纪人:定机票
周杰伦:唱青花瓷
经纪人:收尾款
- Proxy.newProxyInstance()
Proxy的newInstance方法对这个实例对象代理生成一个代理对象。看下newProxyInstance()的接口定义
各个参数的具体含义:
- loder,选用的类加载器。因为代理的是star,所以一般都会用加载star的类加载器。
- interfaces,被代理的类所实现的接口,这个接口可以是多个。
- h,绑定代理类的一个方法。
loder和interfaces基本就是决定了这个类到底是个怎么样的类。而h是InvocationHandler,决定了这个代理类到底是多了什么功能。所以动态代理的内容重点就是这个InvocationHandler。
- InvocationHandler接口
InvocationHandler作用就是,当代理对象的原本方法被调用的时候,会绑定执行一个方法,这个方法就是InvocationHandler里面定义的内容,同时会替代原本方法的结果返回。
invoke方法各个参数的具体含义:
- proxy,代理的实例对象。
- method,对象被调用的方法。
- args,调用时的参数。
- 动态代理的使用场景
动态代理的好处我们从例子就能看出来,它比较灵活,可以在运行的时候才切入改变类的方法,而不需要预先定义它。
动态代理在Java中有着广泛的应用,比如Spring AOP、Hibernate数据查询、测试框架的后端mock、RPC远程调用、Java注解对象获取、日志、用户鉴权、全局性异常处理、性能监控,甚至事务处理等。
标签:star,记录,void,经纪人,代理,println,动态,public From: https://blog.csdn.net/qq_57036151/article/details/139469097