静态代理与JDK动态代理

静态代理与JDK动态代理

代理

生活中的代理:比如帮我们买东西的代购,还有媒婆、中介、商家…都属于代理

静态代理

概念:

1、使用Java文件实现,自己手工实现一个代理类

2、代理目标是确定的

特点:

优点:

1、实现简单

2、容易理解

缺点:

1、当目标类较多时:会产生大量的代理类

2、当接口改变时:影响的目标类较多

实现静态代理的步骤:

1、创建接口,定义方法,表示目标和代理要做的事情。

2、创建目标类,实现接口

3、创建代理类,实现接口(实现了功能的增强)

4、创建客户端类,调用代理进行一个操作。

举例:
//定义一个接口
public interface GoPlay {
    void play();
}

//创建目标类、实现接口
public class Basketball implements GoPlay{
    @Override
    public void play() {
        System.out.println("打篮球!");
    }
}

//创建代理类,实现接口(实现了功能的增强)
public class GoPlayProxy implements GoPlay{
 	//声明一个接口GoPlay类型变量
    private GoPlay goplay;
 
    public GoPlayProxy(GoPlay goplay){
        this.goplay = goplay;
    }
 
    @Override
    public void play() {
        //预处理
        System.out.println("预处理");
        goplay.play();//执行目标对象的方法
 
        //后置处理
        System.out.println("后置处理");
    }
}

//创建客户端类,调用代理进行一个操作。
public class StaticProxyDemo {
    public static void main(String[] args) {
        //创建实际的目标对象
        GoPlay goplay = new GoPlay();
 
        //代理对象,把目标对象封装到代理对象中,建立代理关系
        GoPlayProxy proxy = new GoPlayProxy(goplay);
 
        proxy.play();
    }
}

jdk动态代理

概念:

使用Java反射包中的类和接口实现动态代理的功能。

1、反射,Method类,表示方法。类中的方法,通过Method可以执行某个方法。

2、jdk动态代理的实现

反射包 java.lang.reflect, 里面有三个类:InvocationHandler, Method, Proxy。

特点:

优点:

1、不用创建类文件

2、不用给不同的目标随时创建代理

1、InvocationHandler 接口
中文名:调用处理器
作用:表示代理要做的事
使用方法:
	1、创建InvocationHandler接口的实现类
	2、重写invoke()方法,把原来静态代理中代理类要完成的功能,写到这个地方
2、invoke()方法:
public Object invoke(Object proxy, Method method, Object[] args)

Object proxy:jdk创建的代理对象,无需赋值
Method method: 目标类中的方法,jdk提供method对象的
object[] args: 目标类中方法的参数
3、Method类:

作用:通过Method可以执行某个目标类的方法,Method.invoke()

​ Method.invoke(目标对象, 方法的参数)

4、Proxy类:

方法:静态方法:newProxyInstance()

作用:创建代理对象

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
    
ClassLoader loader :类加载器,负责向内存中加载对象的,使用反射获取对象的classLoader。 例如: 类AA.getClass.getClassLoader(), 主要是为了获取目标对象的类加载器。
Class<?>[] interfaces:接口,目标对象实现的接口,也是反射获取的。
InvocationHandler h:是我们自己写的,代理类要完成的功能。
    
Object:就是目标对象的代理对象

实现动态代理的步骤:

1、创建接口,定义目标类要完成的功能

2、创建目标类实现接口

3、创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能

​ 3.1、调用目标方法

​ 3.2、增强功能

4、使用Proxy类的静态方法,创建代理对象。并把返回值转为接口类型

举例:
/**
 * 针对用户访问的数据接口
 */
public interface UserDao {

    /**
     * 添加功能
     */
    void add() ;

    /**
     * 修改功能
     */
    void update() ;

    /**
     * 查询功能
     */
    void select() ;

    /**
     * 删除功能
     */
    void delete() ;
}
/**
 * 针对用户数据访问接口的实现
 */
public class UserDaoImpl implements UserDao {
    @Override
    public void add() {
        System.out.println("添加功能");
    }

    @Override
    public void update() {
        System.out.println("修改功能") ;
    }

    @Override
    public void select() {
        System.out.println("查询功能");
    }

    @Override
    public void delete() {
        System.out.println("删除功能");
    }
}

/**
 * 对业务方法 add,update,select.delete进行增强
 */
public class UserDaoImpl2 implements UserDao {
    @Override
    public void add() {
        System.out.println("权限校验") ;

        System.out.println("执行添加功能");

        System.out.println("产生日志文件");
    }

    @Override
    public void update() {
        System.out.println("权限校验") ;

        System.out.println("执行修改功能");

        System.out.println("产生日志文件");
    }

    @Override
    public void select() {

        System.out.println("权限校验") ;

        System.out.println("执行查询功能");

        System.out.println("产生日志文件");
    }

    @Override
    public void delete() {

        System.out.println("权限校验") ;

        System.out.println("执行删除功能");

        System.out.println("产生日志文件") ;
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 基于代理的处理程序
 */
public class MyInvocation  implements InvocationHandler {

    //要针对谁产生代理:UserDao ud = new UserDaoImpl() ;
    private Object target ;  //因为代理角色可以是任意Java类型,所
    // 以用Object
    public MyInvocation(Object target){
        this.target = target ;
    }


    //方法的返回值就是代理对象
    @Override //就是我们的接口的方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("权限校验") ;

        //调用接口的列表自己的方法:update(),delete(),add(),select()
        //当前实例--->真实角色
        Object obj = method.invoke(target, args); //代理角色产生

        System.out.println("产生日志文件");
        return obj;
    }
}
/**
 * Jdk动态代理:
 * 		是在程序的执行过程中,通过反射产生的代理对象!
 * 		java.lang.reflect.Proxy
 *		jdk动态代理特点:
 *			基于接口实现的
 *		cglib动态代理
 *          基于类实现
 *
 * Proxy
 * 		public static Object newProxyInstance(ClassLoader loader,          参数1:实现的接口的类加载器
 *                                            Class<?>[] interfaces,       参数2:基于接口的字节码文件对象数组
 *                                            InvocationHandler h)         参数3:是接口InvocationHandler :代理的处理程序
 *
 *                                throws IllegalArgumentException
 *
 *                                参数3是一个接口:自定一个类实现这个接口
 *                                重写这个接口中的
 *                                Object invoke(Object proxy,Method method,Object[] args)throws Throwable
 */
public class JdkProxyDemo {
    public static void main(String[] args) {

        //接口多态:测试UserDao
        UserDao ud = new UserDaoImpl() ; //真实角色
        //版本1:现在需要对功能增强,这个代码不合适!
        ud.add();
        ud.update();
        ud.select();
        ud.delete();
        System.out.println("----------------------------------");

        UserDao ud2 = new UserDaoImpl2() ;
        ud2.add();
        ud2.update();
        ud2.select();
        ud2.delete();

        System.out.println("----------------Jdk动态代理------------------");

        //前提是需要一个接口:UserDao

        MyInvocation handler = new MyInvocation(ud) ;
        // public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
        UserDao proxyInstance = (UserDao) Proxy.newProxyInstance(
                ud.getClass().getClassLoader(),
                ud.getClass().getInterfaces(),
                handler);
        proxyInstance.add();
        proxyInstance.update();
        proxyInstance.select();
        proxyInstance.delete();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值