【设计模式】静态代理和动态代理

1.什么是代理?
1.代购,中介,换ip,商家等等
 
使用代理模式的作用:
1.功能增强:在你原有的功能上,增加了额外的功能,新增加的功能,叫做功能增强
2.控制访问:代理类不让你访问目标,例如商家不让用户访问厂家
 
实现代理的方式

1.静态代理:

代理类是自己手工实现的,自己创建一个java类。同时你所要代理的

目标类是确定的。

特点:1)实现简单 2)容易理解
当项目中目标类和代理类很多之后,代理类数量过多
3)当目标类增加了,代理类可能也需要成倍的增加,代理类数量过多
4)当你的接口功能增加了,或者修改了,会影响众多的实现类,厂家类,代理都需要
修改,影响比较多。
例子:模拟用户购买U盘的行为
用户是客户端类
商家:代理,代理某个品牌的U盘
厂家:目标类
三者的关系:用户(客户端)-----商家(代理)---厂家(目标)
商家和厂家都是卖U盘的,他们完成的功能都是一致的,都是卖U盘的
实现步骤
1.创建一个接口,定义卖U盘的方法,表示你的厂家和商家做的事情
2.创建厂家类,实现1步骤的接口
3.创建商家,就是代理类,也需要实现1步骤中的接口
4.创建客户类,


测试用例:

UserService接口

package com.wang.pojo;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void query();
}

UserService接口实现类UserServiceImpl

package com.wang.pojo;

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("查询了一个用户");
    }

}

UserService接口静态代理类

package com.wang.pojo;

public class UserSericeProxy implements UserService{
    private UserService service;

    public void setService(UserService service) {
        this.service = service;
    }

    @Override
    public void add() {
        beforeDoing();
        service.add();
        afterDoing();
    }

    @Override
    public void delete() {
        beforeDoing();
        service.delete();
        afterDoing();
    }

    @Override
    public void update() {
        beforeDoing();
        service.update();
        afterDoing();
    }

    @Override
    public void query() {
        beforeDoing();
        service.query();
        afterDoing();
    }
    private void beforeDoing(){
        System.out.println("代理对象方法执行前");
    }
    private void afterDoing(){
        System.out.println("代理对象方法执行后");
    }
}

 

 
 
2.动态代理:
在静态代理中目标类很多时候,可以使用动态代理,避免静态代理的缺点。
动态代理中目标类即使很多,代理类数量可以很少。
当你修改了接口中的方法时,不会影响代理类
 
 
动态代理:
在程序执行过程中,使用jdk的反射机制,创建代理类对象,并动态指定要代理对象。
换句话说:动态代理是一种创建java对象的能力,让我不用创建taobao类就能创建
代理类对象。
 
在java中,要创建对象:
1.创建类文件,java文件编译为class
2.使用构造方法,创建类的对象
 
 
什么是动态代理?
使用jdk的反射机制,创建对象的能力,创建的时代理类的对象。而不是创建类文件,
不用写。
 
动态: 在程序执行时,调用jdk的方法才能创建代理类的对象
 
 

 

 

 
 
动态代理方式:
第一种,JDk动态代理(理解):使用java反射包中的类和接口实现动态代理的功能
反射包 java.lang.reflect,里面有三各类:InvocationHandler,Method,Proxy.
 
第二种,通过CGLB动态代理(了解):第三方的一个工具库,创建代理对象。
cglib的原理时继承,cglib通过继承目标类,创建它的子类,在子类中重写
父类中同名的方法,实现功能的修改
 
因为cglib是继承,重写方法,所以要求目标类不能是final,方法也不能是final.
cglib要求目标类比较宽松,只要能继承就可以了,cglib在很多框架中都可以使用
,比如mybatis,spring框架中都有使用。
 
cgLib代理
 
 
jdK动态代理
1.反射,Method类,表示方法,类中的方法。通过Method可以执行某个方法。
2.jdk动态代理的实现
反射包 java.lang.reflect,里面有三个类: InvocationHandler,Method,Proxy.
1)InvocationHandler(调用处理器) 接口:就一个方法invoke()
invoke():表示代理对象要执行的功能代码。你的代理类要完成的功能
就写在invoke()中
代理类完成的功能:
1.调用目标方法,执行目标方法的功能
2.功能增强,在目标方法调用时,增加功能
 
 
public Object invoke(Object proxy, Method method, Object[] args) //Object proxy:JDK创建的代理对象,无需赋值。 //Method method:目标类中的方法,jdk提供method对象的 // Object[] args:目标类中的方法参数

 

2)Method类:表示方法的,确切的说就是目标类中的方法
作用:通过Method可以执行某个目标类的方法,Method.invoke();
method.invoke(目标对象,方法的参数);
3)Proxy类:创建对象都是new 类的构造方法()
现在是使用Proxy类的方法,代表new的使用。
方法:静态方法 newProxyInstance() 作用是:创建代理对象,等同于静态代理中的 TaoBao tb=new TaoBao(); public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) //ClassLoader loader 类加载器,负责像内存中加载对象的, 使用反射 //获取对象的ClassLoader 举例 类a a.getClass().getClassLoader() //目标对象的类加载器 //Class<?>[] interfaces 目标对象所实现的接口,也是反射获取的 //InvocationHandler h:我们自己写的,代理类要完成的功能 //返回值 就是代理对象。
 
 
实现动态代理的步骤
//1.创建接口,定义目标类要完成的功能
//2.创建目标类实现接口
//3.创建IncovateHandler接口的实现类,在invoke方法中完成代理类的功能
//功能有二:1.调用目标方法  2.增加功能
//4.使用Proxy类的静态方法,创建代理对象,并把返回值转为接口类型
UsbShell proxy=(UsbShell)Proxy.newProxyInstance(UsbKingFactory.class.getClassLoader(),factory.getClass().getInterfaces(),handler );
//com.sun.proxy.$Proxy0
//通过代理对象执行方法调用,执行handler
//proxy.sell(1),此时执行的是handler中的incoke方法

 

 


 
动态代理能做什么?
可以在不改变原来目标方法功能的前提下,可以在代理中增强自己的功能代理.
程序开发中的意义:
比如,你所在的项目中,有一个功能是其他人(公司的其他部门,其他小组的人)写好的,
你可以使用,
GoNong.class,
GoNong gn=new GoNong(),
gn.print();
你发现这个功能,现在还缺点,不能完全满足我项目的需求,我需要在gn.print()执行后,需要自己在增加代码,用代理实现gn.print()调用时,增加自己代理,而不用改原来的GoNong文件。

测试用例

代理类处理程序接口InvocationHandler实现类

package com.wang.pojo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


//万能的invocationHandler实现类
public class MyInvocationHandler implements InvocationHandler {
    //被代理对象
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    //生成代理对象
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
    //处理代理实例
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //可以在此添加额外功能
        /*
         * 额外功能
         * */

        //
        see();
        return  method.invoke(target,args);
    }
    private void see(){
        System.out.println("房产中介参与租房业务");
    }
}

 

万能动态代理类实现模板

package com.wang.staticProxy.demo04;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//万能的invocationHandler实现类
public class MyInvocationHandler implements InvocationHandler {
    //被代理对象
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    //生成代理对象
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
    //处理代理实例
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //可以在此添加额外功能
        /*
        * 额外功能
        * */

        //
        someMethod();
      Object o=method.invoke(target,args);
     return 0;
}
private void someMethod(){ *** } }

推荐的动态代理相关文章

 

posted @ 2022-06-18 21:39  王广元  阅读(50)  评论(0编辑  收藏  举报
分享到: