代理模式详解

无法访问目标对象,通过代理对象进行访问,而且增强式的访问。适合进行业务的拓展

代理模式的作用

1、控制目标对象的访问

2、增强功能

代理模式的分类

1、静态代理

2、动态代理,又分为JDK动态代理,CGLib动态代理

静态代理

它是代理模式的一种,具备以下特点:

1)目标对象和代理对象实现同一个业务接口

2)目标对象必须实现接口

3)代理对象在程序运行前就已经存在

4)静态代理能够灵活地进行目标对象的切换,却无法进行功能的灵活处理(使用动态代理处理此问题)

静态代理功能实现

业务功能:请明星进行节目表演,

明星刘德华:目标对象(无法直接访问)

经纪人:代理对象(我们可以访问到,跟目标对象对接)

我们 :客户端对象

public class MyTest {
    //测试功能
    @Test
    public  void testAgent(){
/*        Agent agent=new Agent();
        agent.sing();
        //有接口和实现类,必须使用接口指向实现类(规范)
        */
        Service agent=new Agent();
        agent.sing();
    }

面向接口编程

类中的成员变量设计为接口,方法的形参设计为接口,调用时接口指向实现类

测试类

@Test
    public void  testAgent1(){
        Service agent=new Agent(new SuperStarLiu());
        agent.sing();
}

接口

public interface Service {
    //规定唱歌的业务功能
    void sing();
}

代理

package com.service;
/*
* z助力:代理对象 完成除了唱歌主业务之外的其他业务 时间
* 场地 结算 费用
*
* 类中的成员变量设计为接口
* */
public class Agent implements Service{
    public  Service target;//目标对象
    //传入目标对象 方法的参数设计为接口
    public Agent(Service target){
        this.target=target;

    }
    @Override
    public void sing() {
        System.out.println("预定时间");
        System.out.println("预定场地");
        //切记切记:业务功能必须由目标对象亲自实现

//        面向接口编程的调用时接口指向实现类
        target.sing();
        System.out.println("结算费用");

    }
}

目标对象

/*
* 目标对象
*
* */
public class SuperStarZhou implements Service{
    @Override
    public void sing() {
        System.out.println("我是周润发");

    }

/*
* 目标对象 :实现业务接口中的功能 进行唱歌表演
* */
public class SuperStarLiu implements Service{

    @Override
    public void sing() {
        System.out.println("我是华仔,我正在唱歌");
    }
}

动态代理

代理对象在程序运行过程中动态在内存构建,可以灵活的进行业务功能的切换

JDK动态代理

1)目标对象必须实现业务接口

2)JDK代理对象不需要实现业务接口

3)JDK动态代理的对象在程序运行前不存在,在程序运行时动态的在内存中构建

4)JDK动态代理灵活地进行业务功能的切换

5)本类中的方法(非接口中的方法)不能被代理(代理不允许本人接私活)

JDK动态代理用到的类和接口

它是使用现成的工具类完成动态实现。

1)Proxy类   它是java.lang.reflect.Proxy包下的类  它有一个方法

Proxy.newProxyInstance()专门用来生成动态代理对象
ClassLoader loader 类加载器,完成目标对象的加载
 Class<?>[] interfaces 目标对象实现的所有接口
 InvocationHandler h 实现代理功能的接口,我们传入的是匿名内部实现

2)Method类

反射用的类,用来进行目标对象的方法的反射调用

method对象接住我们正在调用的方法sing(),show()

method==sing(),show();

method.invoke();==>手工调用目标方法

3)InvocationHandler接口

它是实现代理和业务功能的,我们在调用时使用匿名内部实现。

@Test
    public void  testA(){
        Service service=new Service() {
            @Override
            public void sing() {
                System.out.println("哈哈哈哈哈哈哈哈哈");
            }
        };
        service.sing();
}

动态代理代码实现

动态代理类

//    返回动态代理对象
    public  Object getAgent(){
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(
//                            创建代理对象
                            Object proxy,
//                          method就是目标法 sing(),show()
                            Method method,
//                          目标方法的参数
                            Object[] args) throws Throwable {
                        //代理功能
                        System.out.println("预定时间");
//                        代理功能
                        System.out.println("预定场地");
//                        主业务功能实现
//                        target.sing(); 写死了方法的调用 不行
                        // 此时可能调用 sing show等等任意方法
                        Object object= method.invoke(target,args);
//                        代理功能
                        System.out.println("结算费用");

                        return object; //切记这是目标方法的返回值

                    }
                }
        );

接口

public interface   Service01 {
    void  sing();
    public String show(int age);
}

    @Override
    public String show(int age) {
        System.out.println("刘德华的age"+age);
        return "liu";
    }
    @Override
    public String show(int age) {
        System.out.println("周润发的age"+age);
        return "zhou";
    }

test

    @Test
    public  void  testJDK1(){
        ProxyFactory factory=new ProxyFactory(new SuperLiu());
        Service01 agent= (Service01) factory.getAgent();
       String s=agent.show(15);
        System.out.println(s);
    }

CGLib动态代理

又称为子类代理,通过动态的在内存中构建子类对象,重写父类的方法进行动态代理功能的增强,

如果目标对象没有实现接口,则只能通过CGLib子类代理来进行功能增强

子类代理是通过字节码框架ASM来实现的.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值