package cn.itcast_05_proxy.service;
/**
 * 这是一个业务的接口,这个接口中的业务就是返回衣服的价格
 */
public interface IBoss {//接口
    int yifu(String size);
}
package cn.itcast_05_proxy.service.impl;

import cn.itcast_05_proxy.service.IBoss;


/**
 * 实现了卖衣服的接口
 * 自定义了自己的业务,卖裤子
 *
 */
public class Boss implements IBoss{
    public int yifu(String size){ //接口的方法
        System.err.println("天猫小强旗舰店,老板给客户发快递----衣服型号:"+size);
        //这件衣服的价钱,从数据库读取
        return 50;
    }
    public void kuzi(){ //不是接口的方法
        System.err.println("天猫小强旗舰店,老板给客户发快递----裤子");
    }
}

不用代理实现:

package cn.itcast_05_proxy.action;

import org.junit.Test;

import cn.itcast_05_proxy.service.IBoss;
import cn.itcast_05_proxy.service.impl.Boss;

public class SaleAction {
    /**
     * 不使用代理,直接调用方法
     * 方法中规定什么业务,就只能调用什么业务,规定什么返回值,就只能输出什么返回值
     */
    @Test
    public void saleByBossSelf() throws Exception {
        IBoss boss = new Boss();
        System.out.println("老板自营!");
        int money = boss.yifu("xxl");// 老板自己卖衣服,不需要客服,结果就是没有聊天记录
        System.out.println("衣服成交价:" + money);
    }
}

用代理实现:

package cn.itcast_05_proxy.proxyclass;

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

import cn.itcast_05_proxy.service.IBoss;
import cn.itcast_05_proxy.service.impl.Boss;

public class ProxyBoss {
    /**
        扩展方法的实现不是加方法。
      IBoss boss = ProxyBoss.getProxy(10,IBoss.class,Boss.class),   boss就是代理类的实例,
      int money = boss.yifu("xxl");
     */
    public static <T> T getProxy(final int discountCoupon,final Class<?> interfaceClass, final Class<?> implementsClass) throws Exception {
        //这里传的参数类型跟hadoop--19的类型不一样
        return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(),new Class[] { interfaceClass }, new InvocationHandler() {
        
            public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {
                
                    Integer returnValue = (Integer) method.invoke(implementsClass.newInstance(), args); // 调用原始对象以后返回的值
                    return returnValue - discountCoupon;
                }
            });
    }
}

/*
当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。

Object invoke(Object proxy, Method method, Object[] args) throws Throwable
proxy:  指代我们所代理的那个真实对象
method:  指代的是我们所要调用真实对象的某个方法的Method对象
args:  指代的是调用真实对象某个方法时接受的参数


Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法,
这个方法的作用就是得到一个动态的代理对象,
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
loader:    一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
interfaces:    一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
h:    一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上


 */
package cn.itcast_05_proxy.action;

import org.junit.Test;

import cn.itcast_05_proxy.proxyclass.ProxyBoss;
import cn.itcast_05_proxy.service.IBoss;
import cn.itcast_05_proxy.service.impl.Boss;

/**
 * 什么是动态代理? 简单的写一个模板接口,剩下的个性化工作,好给动态代理来完成!
 */
public class ProxySaleAction {
    
    /**
     *使用代理,在这个代理中,只代理了Boss的yifu方法
     *定制化业务,可以改变原接口的参数、返回值等
     */
    @Test
    public void saleByProxy() throws Exception {
        IBoss boss = ProxyBoss.getProxy(10,IBoss.class,Boss.class);// 将代理的方法实例化成接口
        //IBoss boss = new Boss();// 将代理的方法实例化成接口
        System.out.println("代理经营!");
        int money = boss.yifu("xxl");// 调用接口的方法,实际上调用方式没有变
        System.out.println("衣服成交价:" + money);
    }
}