Spring 动态代理 静态代理

1、Spring

1.1、核心概念

  • 控制反转,不再需要new对象,交给Bean去做

  • 到了现在,我们不需要去程序中改动,要实现不同的操作,只需要在xml配置文件中进行修改

  • 对象由Spring来创建,管理,装配!

拓展

Spring Boot 构造一切

Spring Cloud协调一切

SpringCloud Data Flow 连接一切

1.2、第一个Spring程序

  1. 先配置环境

    导入jar包,选择spring-webmvc(选择一个最大的,他会导入其他的)

  2. 编写相关代码

先写一个实体类,后面用Spring来创建对象

编写一个资源文件applicationContext.xml(以后对象交给他来创建)

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
​
    <bean id="student" class="com.counter.pojo.Student">
        <property name="name" value="张三"></property>
        <property name="age" value="18"/>//属性注入
    </bean>
</beans>

调用对象

复制代码
 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        
Student student = (Student) context.getBean("student");

静态代理

代理模式的好处

复制代码
- 使得真实角色的操作更加纯粹,不用去关注一些公共的事情,业务
- 公共业务交给代理角色!  实现了业务的分工!
- 公共业务发生扩展的时候,方便集中管理!

代理模式的缺点:

复制代码
一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率会变低~

一般真实对象和代理对象都要实现的方法我们写一个接口

比如房东和代理对象,都要实现功能-----租房,所以我们先写一个接口--租房

再写实体类,比如房东和代理对象实现这个接口

复制代码
public class Host implements Rent {
    String hostname;
​
    @Override
    public void rent() {
        System.out.println("房东租房");
    }
}
复制代码
public class Proxy implements Rent {
    private Host host;
    public Proxy(Host host) {
        this.host = host;
    }
​
    @Override
    public void rent() {
        host.rent();
    }
}

最后我们再写客户端测试:

复制代码
public void test1(){
    Host host = new Host();
    Proxy proxy = new Proxy(host);
    proxy.rent();
}

动态代理

动态代理和静态代理的角色一样,分别为 抽象角色,真实角色,代理角色,使用类

动态代理按照事先方式分为两大类: a)基于接口的动态代理 b)基于类的动态代理

-基于接口-jdk动态搭理

-基于类:cglib

了解两个类:Proxy代理 InvocationHandler调用处理程序

动态代理的好处:

复制代码
- 可以使真实角色的操作更加纯碎,不用去关注一些公共的业务
- 公共也就交给代理角色,实现了业务的分工
- 共欧诺个业务发生扩展的时候,方便几种管理
- 一个动态代理类代理的是一个接口,一般就是对应的一类业务!
- 一个动态代理类,可以代理多个类,只要是实现了同一个接口即可!

步骤

  1. 先写接口

  2. 写接口的Impl UserServiceImpl

    复制代码
    package com.counter.demo02;
    ​
    public class UserServiceImpl implements UserService {
        @Override
        public void Update() {
            System.out.println("Update");
        }
    ​
        @Override
        public void Insert() {
            System.out.println("Insert");
        }
    ​
        @Override
        public void query() {
            System.out.println("query");
        }
    ​
        @Override
        public void Delete() {
            System.out.println("Delete");
        }
    }
  3. 写代理类,可以通过Object写成一个工具类模版 UseServiceProxy

模版变成工具类:

复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
​
public class UseServiceProxy implements InvocationHandler {
    Object target;
    public UseServiceProxy(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Yell();
        Object result =method.invoke(target, args);
        return null;
    }
    public void Yell(){
        System.out.println("大叫!!!");
    }
​

4.客户端调用(代码在下面)

我的理解:我们要调用Proxy.newProxyInstance创建代理

先创建他需要的参数

需要三个参数,加上我们需要创建被代理的对象(实现接口类)

总共四步,加上最后一步调用方法,五步得到代理类

  1. 先创建被代理的对象

  2. 被代理对象的类加载器

  3. 被代理对象的接口的getClass().getInterfaces();

  4. 创建的代理类UseServiceProxy

  5. 调用方法Proxy.newProxyInstance获得代理

复制代码
package com.counter.demo02;
​
import java.lang.reflect.Proxy;
​
public class Client {
    public static void main(String[] args) {
​
        //1 创建被代理的对象
    UserServiceImpl userService = new UserServiceImpl();
        //2 获取需要传递给Proxy的ClassLoader(),获取要代理对象的ClassLoader()
        ClassLoader classLoader = userService.getClass().getClassLoader();
        //3 获取需要传递给Proxy的interfaces,这里的userService只实现了一个接口UserService
        Class[] interfaces = userService.getClass().getInterfaces();
        //4 生成需要传递给Proxy的IncovationHandler实现类,需传入实际执行的对象userServiceImpl
        UseServiceProxy useServiceProxy = new UseServiceProxy(userService);
        //5 至此,我们生成了我们需要的   !!! 代理类
​
        UserService proxy = (UserService) Proxy.newProxyInstance(classLoader,interfaces,useServiceProxy);
        proxy.Delete();
​
    }
}
相关推荐
醇氧1 小时前
Spring 动态注册 Bean 深度解析:从源码到实践
java·后端·spring
zb200641201 小时前
Laravel7.x十大核心特性解析
spring boot·后端·laravel
明月_清风2 小时前
FastAPI 从入门到实战:3 分钟构建高性能异步 API
后端·python·fastapi
小村儿2 小时前
连载10-Sub-agents 深度解析:从源码理解 Claude Code 的分身术
前端·后端·ai编程
他们叫我阿冠2 小时前
Day5学习--SpringBoot详解
spring boot·后端·学习
笨拙的老猴子2 小时前
[特殊字符] Java GC机制详解:G1、ZGC、Shenandoah全面解析与版本演进对比
java·开发语言
枕星而眠2 小时前
Linux 四大进程/线程同步锁详解:互斥锁、读写锁、条件变量、文件锁
linux·c语言·后端·ubuntu·学习方法
IT_陈寒2 小时前
Vite动态导入把我坑惨了,原来要这样用才对
前端·人工智能·后端
砍材农夫2 小时前
物联网 基于netty构建mqtt协议规范(遗嘱与保留消息)
java·开发语言·物联网·netty