静态代理和动态代理的一点点小理解
Java小白最近初次接触静态代理和动态代理感觉有点绕,就先写一下自己的理解吧。
以后有了更深的理解再修改。
代理模式:为其他对象提供一种代理以控制这个对象的访问
目前只接触了静态代理和通过反射实现的动态代理
1.静态代理:代理类和被代理类直接被写死了,即只能代理实现了同一接口的目标类,比较单一。
java">//作为被代理类和代理类的公共接口
interface BreadFactory {
void produce();
}
//被代理类
class KFCBreadFactory implements BreadFactory {
@Override
public void produce() {
System.out.println("生产面包!!!");
}
}
//代理类
class BreadProxyFactory implements BreadFactory {
private BreadFactory factory;//用被代理类实例化,所以下面构造方法传进去的是该接口的实现类
public BreadProxyFactory(BreadFactory factory) {
this.factory = factory;
}
@Override
public void produce() {
//还可以写一些附加操作
//主要操作:被代理类要实现的目的
factory.produce();
}
}
public class StaticProxyTestDemo {
public static void main(String[] args) {
//创建被代理类的对象
KFCBreadFactory kfc = new KFCBreadFactory();
//创建代理类的对象,用被代理类对象作为参数传入
BreadProxyFactory proxy = new BreadProxyFactory(kfc);
proxy.produce();
}
}
执行结果
通过上面代码可以发现,实现被代理类的需求时,并没有直接调用被代理类对象的方法,而是通过代理类间接调用的代理类。想要生产面包,其实是由代理类代为进行生产的,被代理类本身其实并不直接生产。就比如服装品牌,它其实不自己制造服装,而是委托给代工厂进行生产。又或者说生活中找中介租房子,你就是被代理对象的,中介就是代理对象,你不用直接去找房子,你只需要把需求告诉给中介,他会帮你处理。而通过代理的好处就是可以在不改变被代理类原有代码结构的基础上,可以在代理过程种加上一些其他操作,就是功能增强的意思。
2.动态代理:通过反射去造被代理类的代理类对象,传什么被代理类对象进去,就通过反射造需要的代理类对象,即动态获取代理类对象。
①首先,被代理类还是和静态代理一样。
②而代理类对象就是通过反射动态获取,即使用java.lang.reflect包下的Proxy类和InvocationHandler接口实现动态生成代理对象。
通过调用Proxy类中的**newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)**创建代理对象
**该方法中第一个参数为类的加载器:**因为代理类是要代理被代理类,所以他们的类加载器相同,所以代理的类加载器就可以通过
传入的被代理类对象的基础上通过反射的方法获取,即:被代理类对象.getClass().getClassLoader()
**第二个参数为接口数组:**由于被代理类可能实现了不止一个接口,所以用的数组作为参数,由静态代理例子可知,代理类是要完成
被代理类的所有需求的,那么代理类就一定要实现被代理类实现了的所有接口。也是通过传入的被代理类对象的基础由反射的方式获取
即:被代理类对象.getClass().getInterface()
第三个参数为InvocationHandler接口实现类的对象: InvocationHandler接口中只有一个抽象方法
该方法是,当我们通过代理类对象调用被代理类方法时,就会自动调用该invoke()方法,然后通过调用该方法中method调用的另外一个
invoke()方法去调用被代理类的方法。
可以看到该抽象方法有三个参数
第一个参数 :一般用不到,无需赋值
第二个参数:是调用的方法,无需赋值。
该方法有两个参数
第一个参数:是被代理类对象,需要我们自己传入。可以选择在InvocationHandler实现类中提供一个Object类型的参数来接收被代理类对象,赋值操作可以由该实现类的构造方法完成,也可单独写个方法,通过该实现类对象调用完成。
第二个参数:是个可变形参,是我们需要调用的方法中的参数,即为三个参数的invoke()方法中的第三个参数来确定
第三个参数 目标类中的方法的参数,jdk提供
java">//公共接口
interface Bread{
void produce();
}
//被代理类
class KFCBread implements Bread{
@Override
public void produce() {
System.out.println("生产KFC面包");
}
}
//公共接口
interface Book {
void price(double pri);
}
//被代理类
class MathBook implements Book {
@Override
public void price(double pri) {
System.out.println("价格为:" + pri);
}
}
//InvocationHandler实现类
class MyInvocation implements InvocationHandler {
public Object obj;
public MyInvocation(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("其他操作");
Object invo = method.invoke(obj, args);
return invo;
}
}
//代理类生成类
class ProxyFactoryx {
public static Object proxyInstancex(Object obj) {
MyInvocation mi = new MyInvocation(obj);
//根据传入的被代理类对象通过反射生成相应的代理类对象并返回
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), mi);
}
}
//测试类
public class ProxyTestx {
public static void main(String[] args) {
//被代理类对象
MathBook mtb = new MathBook();
//代理类对象
Book o = (Book) ProxyFactoryx.proxyInstancex(mtb);
o.price(39.9);
System.out.println("-------------分割线----------------");
//被代理对象
KFCBread kb = new KFCBread();
//代理类对象
Bread bd = (Bread) ProxyFactoryx.proxyInstancex(kb);
bd.produce();
}
}
执行结果
over!