一、动态代理基础

1、静态代理

还有一种是继承的方式,代理类直接继承目标类(被代理类),重写需要增强的方法
目标类和代理类实现同一接口,代理对象中包含目标对象

/**
 * 静态代理:
 *      对一个新的接口需要创建新的代理类 和 被代理类
 */
public class ProxyTest1 {
    public static void main(String[] args) {
        NikeClothFactory nike = new NikeClothFactory();//创建被代理类的对象
        ProxyFactory proxy = new ProxyFactory(nike);//创建代理类的对象
        proxy.productCloth();
    }
}
/**
 * 接口
 */
interface ClothFactory{
    void productCloth();
}
/**
 * 被代理类
 */
class NikeClothFactory implements ClothFactory{
    @Override
    public void productCloth() {
        System.out.println("Nike工厂生产一批衣服");
    }
}
/**
 * 代理类
 */
class ProxyFactory implements ClothFactory{
    private ClothFactory cf;
    //创建代理类的对象时,实际传入一个被代理类的对象
    ProxyFactory(ClothFactory cf){
        this.cf = cf;
    }
    @Override
    public void productCloth() {
        System.out.println("代理类开始执行,收代理费$1000");
        cf.productCloth();
    }
}
执行main方法:
代理类开始执行,收代理费$1000
Nike工厂生产一批衣服

2、JDK动态代理

/**
 * 动态代理
 */
public class ProxyTest2 {
    public static void main(String[] args) {
        //1.被代理类的对象
        RealSubject real = new RealSubject();
        //2.创建一个实现了InvocationHandler接口的类的对象
        MyInvocationHandler handler = new MyInvocationHandler();
        //3.调用blind()方法,动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象。
        Object obj = handler.blind(real);
        Subject sub = (Subject)obj;//此时sub就是代理类的对象
        sub.action();//转到对InvocationHandler接口的实现类的invoke()方法的调用
        //再举一例
        NikeClothFactory nike = new NikeClothFactory();
        ClothFactory proxyCloth = (ClothFactory)handler.blind(nike);//proxyCloth即为代理类的对象
        proxyCloth.productCloth();
    }
}
interface Subject {
    void action();
}
// 被代理类
class RealSubject implements Subject {
    public void action() {
        System.out.println("被代理类正在被执行...");
    }
}
class MyInvocationHandler implements InvocationHandler {
    private Object obj;// 实现了接口的被代理类的对象的声明,真实对象
    public Object blind(Object obj) {
        // ① 给被代理的对象实例化
        this.obj = obj;
        // ② 返回一个代理类的对象
        /**
         * Proxy.newProxyInstance()的三个参数:
         *  1、obj.getClass().getClassLoader() 使用和被代理类相同的类加载器
         *  2、obj.getClass().getInterfaces()  实现和被代理类相同的接口
         *  3、this                            实现了InvocationHandler接口的对象,即MyInvocationHandler用this来代替
         */
        return Proxy.newProxyInstance(
                obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(),
                this);
    }
    // 当通过代理类的对象发起对被代理类方法的调用时,都会转换为对如下的invoke方法的调用
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //method方法的返回值时returnVal
        return method.invoke(obj, args);
    }
    执行main方法:
    被代理类正在被执行...
	Nike工厂生产一批衣服
}
获取指定的被代理类对象,对被代理类对象的方法进行增强
public interface IEat {
    void breakfast();
    void lunch();
    void dinner();
}
public class Eat implements IEat {
    @Override
    public void breakfast() {
        System.out.println("吃早饭!");
    }
    @Override
    public void lunch() {
        System.out.println("吃午饭!");
    }
    @Override
    public void dinner() {
        System.out.println("吃晚饭!");
    }
}
public class Wash {
    public void washHands(){
        System.out.println("吃饭之前洗手。。。。");
    }
    public void washDishes(){
        System.out.println("吃完饭洗盘子。。。。");
    }
}
public class ProxyEat {
    private final Eat eat = new Eat();
    private Wash wash = new Wash();
    public IEat getProxyEat(){
        return (IEat) Proxy.newProxyInstance(
                eat.getClass().getClassLoader(),
                eat.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        wash.washHands();
                        Object invoke = method.invoke(eat, args);
                        wash.washDishes();
                        return invoke;
                    }
                }
        );
    }
}
public class ProxyTest {
    public static void main(String[] args) {
        System.out.println("==========被代理类执行吃饭========");
        Eat eat = new Eat();
        eat.breakfast();
        eat.lunch();
        eat.dinner();
        System.out.println("==========代理类执行吃饭=========");
        ProxyEat proxyEat = new ProxyEat();
        IEat newEat = proxyEat.getProxyEat();
        newEat.breakfast();
        newEat.lunch();
        newEat.dinner();
    }
}
==========被代理类执行吃饭========
吃早饭!
吃午饭!
吃晚饭!
==========代理类执行吃饭=========
吃饭之前洗手。。。。
吃早饭!
吃完饭洗盘子。。。。
吃饭之前洗手。。。。
吃午饭!
吃完饭洗盘子。。。。
吃饭之前洗手。。。。
吃晚饭!
吃完饭洗盘子。。。。
实现对任意被代理类对象方法的增强
public interface Human {
    void info();
    void work();
}
public class IronMan implements Human{
    @Override
    public void info() {
        System.out.println("我是一个钢铁侠");
    }
    @Override
    public void work() {
        System.out.println("钢铁侠开炮了");
    }
}
public class SuperMan implements Human{
    @Override
    public void info() {
        System.out.println("我是一个超人");
    }
    @Override
    public void work() {
        System.out.println("超人穿上了红内裤");
    }
}
public class Actor {
    public void present(){
        System.out.println("演员出场了");
    }
    public void exit(){
        System.out.println("演员下班了");
    }
}
public class MyInvocationHandler implements InvocationHandler {
    //声明被代理类对象
    private Object object;

    public void setObject(Object object) {
        this.object = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Actor actor = new Actor();
        actor.present();
        Object value = method.invoke(object, args);
        actor.exit();
        return value;
    }
}
public class ProxyFactory {
    public static Object getProxyInstance(Object object){
        MyInvocationHandler handler = new MyInvocationHandler();
        handler.setObject(object);
        return Proxy.newProxyInstance(
                object.getClass().getClassLoader(),
                object.getClass().getInterfaces(),
                handler
        );
    }
}
public class TestAOP {
    @Test
    public void test1(){
        SuperMan superMan = new SuperMan();
        Human human = (Human)ProxyFactory.getProxyInstance(superMan);
        human.info();
        System.out.println();
        human.work();
    }
   
    @Test
    public void test2(){
        IronMan ironMan = new IronMan();
        Human human = (Human)ProxyFactory.getProxyInstance(ironMan);
        human.info();
        System.out.println();
        human.work();
    }
}

输出

输出:test1()              test2()
    演员出场了              演员出场了 
	我是一个超人			  我是一个钢铁侠
	演员下班了              演员下班了
	
	演员出场了              演员出场了
	超人穿上了红内裤         钢铁侠开炮了
	演员下班了              演员下班了

CGLIB动态代理

<dependencies>
   <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>2.1_3</version>
    </dependency>
</dependencies>
public class Producer {
    /**
     * 销售
     * @param money
     */
    public void saleProduct(float money){
        System.out.println("厂家销售产品,并拿到钱:" + money);
    }

    /**
     * 售后
     * @param money
     */
    public void afterService(float money){
        System.out.println("厂家提供售后服务,并拿到钱:" + money);
    }
}
/**
 * @auther Mr.Liao
 *
 * 动态代理:
 *      特点:字节码随用随创建,随用随加载
 *      作用:不修改源码的基础上对方法增强
 *      分类:
 *          基于接口的动态代理
 *          基于子类的动态代理
 *      基于子类的动态代理:
 *          涉及的类:Enhancer
 *          提供者:第三方cglib库
 *      如何创建代理对象:
 *          使用Enhancer类中的create方法
 *      创建代理对象的要求:
 *          被代理类不能是最终类
 *      create方法的参数:
 *          1、Class:字节码,它是用于指定被代理对象的字节码。
 *          2、Callback:用于提供增强的代码
 *               它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
 *               此接口的实现类都是谁用谁写。
 *               我们一般写的都是该接口的子接口实现类:MethodInterceptor
 */
public class Client {
    public static void main(String[] args) {
        final Producer producer = new Producer();
        Producer cglibProducer = (Producer)Enhancer.create(
                producer.getClass(),
                new MethodInterceptor() {
            /**
             * 执行被代理对象的任何方法都会先执行此方法
             * @param object
             * @param method
             * @param objects
             * @param methodProxy 当前执行方法的代理对象
             * @return
             * @throws Throwable
             */
            public Object intercept(Object object, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                // 提供增强的方法
                Object res = null;
                //1、获取方法执行的参数
                Float money = (Float) objects[0];
                //2、判断当前方法是不是销售
                if ("saleProduct".equals(method.getName())) {
                    res = method.invoke(producer, money * 0.8f);
                }
                return res;
            }
        });
        cglibProducer.saleProduct(12000f);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值