静态代理与动态代理
静态代理
静态代理:特征是代理类和目标对象的类都是在编译期间确定下来,不利于程序的扩展。
同时,每一个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理,
最好可以通过一个代理类完成全部的代理功能。
动态代理
动态代理:
使用一个代理将对象包装起来,然后用该代理对象取代院士对象。任何对原始对象的调用都要通过代理,代理对象决定是否以及何时将
方法调用到原始对象上
动态代理是指客户通过代理类来调用其他对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象
动态代理的使用场合:
>调试
>远程方法调用
动态代理相比静态代理的优点:
抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理。这样,我们可以更加灵活和同一的处理众多的方法
静态代理的创建流程
创建接口
interface ClothFactory{
void produceCloth();
}
创建代理类
注意点:
1.代理类中应当声明被代理类的对象
2.应当声明参数为被代理类对象的构造器
class ProxyClothFactory implements ClothFactory{
private ClothFactory factory;//使用被代理类对象进行实例化
public ProxyClothFactory(ClothFactory factory){
this.factory = factory;
}
@Override
public void produceCloth() {
System.out.println("代理工厂准备工作");
factory.produceCloth();
System.out.println("代理工厂收尾工作");
}
}
创建被代理类
class NikeClothFactory implements ClothFactory{
@Override
public void produceCloth() {
System.out.println("Nike工厂生产一批衣服");
}
}
方法的测试
public class StaticProxyTest {
public static void main(String[] args) {
//造被代理类对象
NikeClothFactory nk = new NikeClothFactory();
//造代理类
ProxyClothFactory pcf = new ProxyClothFactory(nk);
//调用方法
pcf.produceCloth();
}
}
输出结果:
代理工厂准备工作
Nike工厂生产一批衣服
代理工厂收尾工作
动态代理的创建流程
创建接口
interface Human{
String getBelief();
void eat(String food);
}
创建被代理类
class superMan implements Human{
@Override
public String getBelief() {
return "I believe i can fly";
}
@Override
public void eat(String food) {
System.out.println("喜欢吃" + food);
}
}
创建InvocationHandler的实现类
注意:
1.此类中声明的属性obj即为被代理类的对象
2.InvocationHandler中重写的invoke方法:当通过代理类的对象调用某个方法,就会直接调用如下的invoke方法
此方法中需要填入三个参数
>参数1:被代理类的对象。
>参数2:method代表的是代理类的对象调用的方法,因此要将被代理类要执行的方法声明在invoke方法中.
>参数3:反射中invoke方法需要提供的参数
3.method调用的invoke方法,此方法可以让参数1所提供的类调用method所代表的方法。
class myInvocationHandler implements InvocationHandler{
private Object obj;//虽然声明为Object,但是赋值时需要使用被代理类的对象进行赋值
public void bind(Object obj){
this.obj = obj;
}
//当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法,invoke
//当代理类的对象调用方法时,会自动调用handler中的方法,所以就需要将被代理类要执行的方法a的功能声明在invoke中
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
HumanUtil util = new HumanUtil();
//参数一:代理类的对象。参数二;代理类的对象需要调用的方法。
//此时method就是代理类对象调用的方法,此方法也就作为了被代理类对象瑶调用的方法
//obj:被代理类的对象
Object returnvalue =method.invoke(obj,args);
//上述方法的返回值就作为当前类中invoke方法中的返回值
return returnvalue;
}
}
创建动态代理类
动态代理类主要用处是用来动态的创建被代理类的代理类对象
注意:
1.创建一个方法用来动态创建被代理类的对象
2.需要借助java.lang.reflect 包中的 Proxy 类的newProxyInstance方法
3.newProxyInstance:此方法中有三个参数
>参数1: 被代理类的加载器
>参数2:被代理类实现的接口
>参数3:InvocationHandler接口的实现类的对象
4.此类创建代理类之后,当代理类调用方法时,会自动调用InvocationHandler的实现类中重写的invoke方法。
class ProxyFactory{
public static Object getProxyInstance(Object obj){//obj:被代理类的对象
//创建invocationHandler的对象
myInvocationHandler handler = new myInvocationHandler();
//调用反射API下的类:Proxy
//Proxy.newProxyInstance:创建一个代理类的对象。
// 参数一:被代理类的加载器。参数二:接口。参数三:接口InvocationHandler的实现类
handler.bind(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
}
}
动态代理的测试
public class ProxyTest {
public static void main(String[] args) {
superMan superMan = new superMan();
//创建了代理类对象
Human supe =(Human) ProxyFactory.getProxyInstance(superMan);
//当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法
System.out.println(supe.getBelief());
supe.eat("水果");
System.out.println("*******************体现动态性*********");
NikeClothFactory nikeClothFactory = new NikeClothFactory();
//动态创建代理类的对象
ClothFactory proxyInstance =(ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);
proxyInstance.produceCloth();
}
}
输出结果:
通用方法一
通用方法二
I believe i can fly
通用方法一
喜欢吃水果
通用方法二
**********体现动态性
通用方法一
Nike工厂生产一批衣服
通用方法二
动态代理与AOP
AOP:Aspect Orient Programming
AOP代理的方法:创建一个包含通用方法的类,将需要的通用方法加入invoke中即可。(现在还不会,等会了以后再回来补齐阿巴阿巴)。
总结:TMD好难(×)
动态代理相比静态代理,其运用了java中的反射机制,从而可以更加的灵活。
两者的创建过程基本相同,即:
1.需要有共同实现的接口
2.需要创建被代理类
不同之处:
1.动态代理需要实现InvocationHandler接口。
2.动态代理的代理类需要使用Proxy类的方法灵活创建被代理类的对象
只是初学萌新的一些理解,希望大佬指正。