首页 > 编程语言 > 详细

Spring05:静态、动态代理

时间:2021-05-11 16:19:31      阅读:16      评论:0      收藏:0      [点我收藏+]

1、代理模式

为什么要学习代理模式,因为AOP的底层机制就是动态代理!

代理模式:

  • 静态代理
  • 动态代理

学习aop之前 , 我们要先了解一下代理模式!

2、静态代理

静态代理角色分析

  • 抽象角色 : 一般使用接口或者抽象类来实现
  • 真实角色 : 被代理的角色
  • 代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作 .
  • 客户 : 使用代理角色来进行一些操作

代码实现

1、Spring配置类

@Configuration
@ComponentScan("org.com.pojo")
public class MyConfig {

}

2、抽象角色

public interface Rent {

    void rent();

}

3、真实角色

@Component("host")
public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房屋出租成功!");
    }
}

4、代理角色

@Component("proxy")
public class StaticProxy implements Rent {
    @Autowired
    private Host host;
    @Override
    public void rent() {
        seeHouse();
        host.rent();
        fare();
    }

    //看房
    private void seeHouse(){
        System.out.println("带房客看房");
    }
    //收中介费
    private void fare(){
        System.out.println("收中介费");
    }
}

5、客户

public class Client {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        StaticProxy proxy = context.getBean("proxy", StaticProxy.class);
        proxy.rent();

    }

}

分析:在这个过程中,你直接接触的就是中介,就如同现实生活中的样子,你看不到房东,但是你依旧租到了房东的房子通过代理,这就是所谓的代理模式,程序源自于生活,所以学编程的人,一般能够更加抽象的看待生活中发生的事情。

静态代理的好处

  • 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
  • 公共的业务由代理来完成 . 实现了业务的分工 ,
  • 公共业务发生扩展时变得更加集中和方便 .

缺点 :

  • 类多了 , 多了代理类 , 工作量变大了 . 开发效率降低

我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理 !

我们在不改变原来的代码的情况下,实现了对原有功能的增强,这是AOP中最核心的思想

聊聊AOP:纵向开发,横向开发

技术分享图片

3、动态代理

  • 动态代理的角色和静态代理的一样 .

  • 动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的

  • 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理

    • 基于接口的动态代理:JDK动态代理
      - 基于类的动态代理:cglib
      - java字节码实现:javasist(这里不详细说,原理都一样)

3.1、JDK的动态代理

核心 : InvocationHandler 和 Proxy , 打开JDK帮助文档看看

【InvocationHandler:调用处理程序】

技术分享图片

技术分享图片

【Proxy : 代理】

技术分享图片

技术分享图片

技术分享图片

1、注册bean

@Bean
public Object target(){
    return new Host();
}

2、创建动态代理角色

@Component("proxyInvocationHandler")
public class ProxyInvocationHandler implements InvocationHandler {


    @Autowired
    @Qualifier("target")
    private  Object target;

    //生成代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色
    public  Object getProxyInstance(){
        return Proxy.newProxyInstance(ProxyInvocationHandler.class.getClassLoader(),
                target.getClass().getInterfaces(), this);
    }

   // proxy : 代理类 method : 代理类的调用处理程序的方法对象.
   // 处理代理实例上的方法调用并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        //核心:本质利用反射实现!
        Object result = method.invoke(target, args);
        fare();
        return result;
    }

    //看房
    private void seeHouse(){
        System.out.println("带房客看房");
    }
    //收中介费
    private void fare(){
        System.out.println("收中介费");
    }
}

3、客户角色

public class Client {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        //代理实例的调用处理程序
        ProxyInvocationHandler proxyInvocationHandler = context.getBean("proxyInvocationHandler", ProxyInvocationHandler.class);
        //动态生成对应的代理类!
        Rent proxyInstance = (Rent)proxyInvocationHandler.getProxyInstance();
        proxyInstance.rent();
    }

}

核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!、

动态代理的好处

静态代理有的它都有,静态代理没有的,它也有!

  • 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
  • 公共的业务由代理来完成 . 实现了业务的分工 ,
  • 公共业务发生扩展时变得更加集中和方便 .
  • 一个动态代理 , 一般代理某一类业务
  • 一个动态代理可以代理多个类,代理的是接口!

3.2 cglib代理

JDK的动态代理也有个约束:目标对象一定是要有接口的,没有接口就不能实现动态代理,因此出现了cglib代理

cglib代理也叫子类代理,从内存中构建出一个子类来扩展目标对象的功能!

  • CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。

cglib使用步骤:

1、引入jar包

技术分享图片

2、取消Host实现的接口

@Component("host")
public class Host {

    public void rent() {
        System.out.println("房屋出租成功!");
    }
}

3、代理角色

@Component("cglibProxy")
public class CglibProxy implements MethodInterceptor {

    // 维护目标对象
    @Autowired
    @Qualifier("target")
    private Object target;


    // 给目标对象创建代理对象
    public Object getProxyInstance() {
        //1. 工具类
        Enhancer en = new Enhancer();
        //2. 设置父类
        en.setSuperclass(target.getClass());
        //3. 设置回调函数
        en.setCallback(this);
        //4. 创建子类(代理对象)
        return en.create();
    }


    @Override
    public Object intercept(Object obj, Method method, Object[] args,
                            MethodProxy proxy) throws Throwable {

        seeHouse();
        // 执行目标对象的方法
        Object returnValue = method.invoke(target, args);
        fare();
        return returnValue;
    }

    //看房
    private void seeHouse(){
        System.out.println("带房客看房");
    }
    //收中介费
    private void fare(){
        System.out.println("收中介费");
    }
}

4、客户角色

public class Client {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        CglibProxy cglibProxy = context.getBean("cglibProxy", CglibProxy.class);
        Host proxyInstance = (Host)cglibProxy.getProxyInstance();
        proxyInstance.rent();
    }

}

使用cglib就是为了弥补JDK动态代理的不足【动态代理的目标对象一定要实现接口】

Spring05:静态、动态代理

原文:https://www.cnblogs.com/javaconner/p/14754788.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!