泛型 + 反射 + 注解 + 动态代理 + 设计模式 + Factory(BeanFactory,FactoryBean)

1.泛型

编译器可以对泛型参数进行检测,并且通过泛型参数可以指定传入的对象类型。比如 ArrayList<Person> persons = new ArrayList<Person>() 这行代码就指明了该 ArrayList 对象只能传入 Person 对象,如果传入其他类型的对象就会报错。

原生 List 返回类型是 Object ,需要手动转换类型才能使用,使用泛型后编译器自动转换

ArrayList list = new ArrayList();
    list.add("aaa");
System.out.println((String)list.get(0));
ArrayList<String> list = new ArrayList<>();
    list.add("aaa");

https://blog.csdn.net/weixin_45395059/article/details/126006369

泛型一般有三种使用方式:泛型类、泛型接口、泛型方法

泛型类

public class Generic<T>{

    private T key;

    public Generic(T key) {
        this.key = key;
    }

    public T getKey(){
        return key;
    }
}

T 是泛型标识被称作是类型参数,用于指代任何数据类型。泛型标识是任意设置的

泛型类中的静态方法和静态变量不可以使用泛型类所声明的类型参数

  • 泛型类中的类型参数的确定是在创建泛型类对象的时候(例如 ArrayList< Integer >)。
  • 而静态变量和静态方法在类加载时已经初始化,直接使用类名调用;在泛型类的类型参数未确定时,静态成员有可能被调用,因此泛型类的类型参数是不能在静态成员中使用的。

泛型接口

public interface Generator<T> {
    public T method();
}

实现:

class GeneratorImpl<T> implements Generator<T>{
    @Override
    public T method() {
        return null;
    }
}

泛型方法

public static < E > void printArray( E[] inputArray )
   {
         for ( E element : inputArray ){
            System.out.printf( "%s ", element );
         }
         System.out.println();
    }

2.反射

通过反射你可以获取任意一个类的所有属性和方法,你还可以调用这些方法和属性。
加载类,允许以变成 的方式解剖类中的各种成分(成员变量、方法、构造器等)
(1)加载类,获取字节码:class对象
(2)获取类的构造器:constructor对象
(3)获取成员变量:Field
(4)获取类成员方法:Method

(1)获取Class对象
在这里插入图片描述
在这里插入图片描述
True,True,True
c1,c2,c3都是相同的,都是Student类的字节码

(2)获取构造器
在这里插入图片描述

获取构造器的作用:依然是初始化对象返回

(3)获取成员变量
在这里插入图片描述
作用:赋值、取值
在这里插入图片描述
(4)获取成员方法
在这里插入图片描述
触发方法,Object obj 是要传一个对象 。这里可以方法可能会使用创建对象才有的变量,所以必须要有实例对象才能执行方法
在这里插入图片描述

反射做框架

对于任意一个对象,该框架都可以把对象的字段名和对应的值,保存到文件中去。
在这里插入图片描述
用反射设计一个框架来解决

//目标:保存任务一对象的字段和数据到文件中去
public static void saveobject(Object obj){
//1.obj是任务对象,到底有多少字段要保存
	Class c = obj,getClass();
//2.从类中提取它的全部成员变量
	Fielf[] fields = c.getDeclaredFields();
//3.遍历每个成员变量
	for(Field field:fields){
		//4.拿到成员变量的名字
		String name = field.getName;
		//5.拿到成员变量在对象中的数据
		String value = field.get(obj)+"" ;
	}

}

在苍穹外卖中的实例:

Object entity = args[0];//实体对象

//准备赋值的数据
LocalDateTime now = LocalDateTime.now();//时间
Long currentId = BaseContext.getCurrentId();//用户ID

//根据当前不同的操作类型,为对应的属性通过反射来赋值
if (value == OperationType.INSERT) {
    //插入:为4个公共字段赋值
    try {//反射拿到类方法
        Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
        Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
        Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
        Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
        //通过反射赋值
        setCreateTime.invoke(entity, now);
        setUpdateTime.invoke(entity, now);
        setCreateUser.invoke(entity, currentId);
        setUpdateUser.invoke(entity, currentId);
    } catch (Exception e) {
        e.printStackTrace();
    }

这些框架中也大量使用了动态代理,而动态代理的实现也依赖反射

3.注解

Annotation 其实就是代码里的特殊标记, 这些标记可以在编译, 类加载, 运行时被读取, 并执行相应的处理。
通过使用Annotation, 程序员可以在不改变原有逻辑的情况下, 在源文件中嵌入一些补充信息
代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或者进行部署

原文链接:https://blog.csdn.net/weixin_52533007/article/details/127487847

  1. 注解本质是一个继承了Annotation 的特殊接口:
  2. @注解(...)其实就是一个实现类对象,实现了该注解以及Annotation接口
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)//之作用在源码阶段
public @interface Override {

}

public interface Override extends Annotation{

}

  1. 注解只有被解析之后才会生效,常见的解析方法有两种:
  • 编译期直接扫描:编译器在编译 Java 代码的时候扫描对应的注解并处理,比如某个方法使用@Override 注解,编译器在编译的时候就会检测当前的方法是否重写了父类对应的方法。
  • 运行期通过反射处理:像框架中自带的注解(比如 Spring 框架的 @Value、@Component)都是通过反射来进行处理的。

自定义注解

在这里插入图片描述
实例:自定义注解
Annotation.AutoFill.java

@Target(ElementType.METHOD)//指定注解只能加载方法上
@Documented
@Retention(RetentionPolicy.RUNTIME)//控制下面的注解一直保留到运行时
public @interface AutoFill {
    //通过枚举-指定当前属性OperationType就两种 Update 和 Insert
    OperationType value();
}

mapper:

 @AutoFill(OperationType.INSERT)//这里本质是在创建注解的实现类对象
 @Insert("insert into category(type, name, sort, status, create_time, update_time, create_user, update_user)" +
            " VALUES" +
            " (#{type}, #{name}, #{sort}, #{status}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser})")
 void insert(Category category);

元注解

在这里插入图片描述

注解示例: 模拟junit程序

对有@MyTest注解的方法执行

public static void mai(String[] args){
	AnnotationTest4 a= new AnnotationTest4();
	//1.得到Class对象
	Class c = AnnotationTest4.class;
	//2.提取全部成员方法
	Method[] methods = c.getDeclareMethods();
	//3.遍历数组中的方法,看否存在@MyTest注解,存在则触发执行
	for(Method method:methods){
		if(method.isAnnotationPresent(MyTest.class)){
			method.invoke(a);
		}
	}
}

注解用来标记某个程序,让其他程序根据注解信息决定怎么去对待它

4.动态代理

使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。
代理模式的主要作用是扩展目标对象的功能,比如说在目标对象的某个方法执行前后你可以增加一些自定义的操作。

从 JVM 角度来说,动态代理是在运行时动态生成类字节码,并加载到 JVM 中的
说到动态代理,Spring AOP、RPC 框架应该是两个不得不提的,它们的实现都依赖了动态代理。
(1)来生成一个代理对象

  • loader :类加载器,用于加载代理对象。
  • interfaces : 被代理类实现的一些接口;
  • h : 实现了 InvocationHandler 接口的对象;
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        ......
    }

(2)要实现动态代理的话,还必须需要实现InvocationHandler 来自定义处理逻辑。 当我们的动态代理对象调用一个方法时,这个方法的调用就会被转发到实现InvocationHandler 接口类的 invoke 方法来调用。

public interface InvocationHandler {

    /**
     * 当你使用代理对象调用方法的时候实际会调用到这个方法
     */
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

invoke() 方法有下面三个参数:

  • proxy :动态生成的代理类
  • method : 与代理类对象调用的方法相对应
  • args : 当前 method方法的参数
  • 也就是说:你通过Proxy 类的 newProxyInstance()创建的代理对象在调用方法的时候,实际会调用到实现InvocationHandler 接口的类invoke()方法。 你可以在invoke() 方法中自定义处理逻辑,比如在方法执行前后做什么事情

以下代码是将上述两者结合表示:
在这里插入图片描述
创建 statProxy来代理的BigStar对象
所以3.的return method.invoke是要用调用BigStar的方法

方便进行模版设计

5.工厂

Spring框架在其设计和实现中使用了多种设计模式,这些设计模式有助于提高代码的可重用性、灵活性和可维护性。以下是一些在Spring中常用的设计模式:

  1. 工厂模式:Spring通过BeanFactory和ApplicationContext来创建对象,其中BeanFactory就是简单工厂模式的体现。工厂模式隐藏了对象实例化的复杂性,并提供一个统一的方式来获取对象。
    应用场景:
    ①当需要一个对象时,我们不需要知道该对象所对应的具体类,只要知道哪个具体工厂可以生成该对象,实例化这个具体工厂即可创建该对象。
    ②类的数目不固定,随时有新的子类增加进来,或者是还不知道将来需要实例化哪些具体类。
    ③定义一个创建对象接口,由子类决定要实例化的类是哪一个;客户端可以动态地指定工厂子类创建具体产品。
    客户只需要知道所需产品的具体工厂,而无须知道具体工厂的创建产品的过程,甚至不需要知道具体产品的类名。
//打工人
public abstract class Worker {
}
 
//志愿者
public class Volunteer extends Worker {
}
 
//大学生
class  Undergraduate extends Worker {
}
 
//工厂
public interface IFactory {
	Worker CreateWorker();
}
//志愿者工厂
public class VolunteerFactory implements IFactory {
	@Override
	public Worker CreateWorker() {
		return new Volunteer();
	}
 
}
 
//大学生工厂
class UndergraduateFactory implements IFactory {
	@Override
	public Worker CreateWorker() {
		return new Undergraduate();
	}
 
}
IFactory factory = new UndergraduateFactory();//new对象类型用接口类型
Worker student = factory.CreateWorker();
	
IFactory factory2 = new VolunteerFactory();//new对象类型用接口类型
Worker volunteer = factory2.CreateWorker();	
  1. 单例模式:在Spring中,默认情况下,bean以单例的形式存在。这意味着对于每个bean定义,Spring容器只会创建一个共享的实例。这样做可以减少系统资源的消耗,并减少垃圾回收器的压力。
  2. 代理模式:Spring的面向切面编程(AOP)功能使用到了JDK的动态代理和CGLIB字节码生成技术。这使得可以在不修改源代码的情况下,为对象添加额外的行为。
  3. 策略模式:例如,Resource接口的不同实现类针对不同的资源文件实现了不同的资源获取策略。策略模式允许在运行时选择算法或操作的具体实现。
  4. 模板方法模式:Spring中的JdbcTemplate、RestTemplate等都是模板方法模式的应用。它们提供了一个操作的框架,而具体的实现步骤则可以由子类来提供,从而实现代码复用和减少重复代码。

Spring的IOC和DI用了什么设计模式

Spring 的 IoC(控制反转)和 DI(依赖注入)使用了工厂模式、单例模式和代理模式等设计模式。具体如下:

(1)工厂模式:IoC 容器负责创建对象,当需要创建一个对象时,只需配置好相应的配置文件或注解,无需关心对象的创建过程。IoC 容器就像一个工厂,它根据配置文件或注解来生成和管理对象实例。
(2)单例模式:在 Spring 框架中,默认情况下单例模式,确保每个 Bean 的生命周期内只有一个共享的实例
(3)代理模式:AOP(面向切面编程)使用代理模式来实现。通过代理模式,可以在不修改原始类代码的情况下,为对象提供额外的功能,例如事务管理和日志记录。
综上所述,这些设计模式共同工作,使得 Spring 框架能够提供一个高度解耦、易于扩展和维护的应用程序架构。

(BeanFactory,FactoryBean)

  1. BeanFactory:是所有Spring Bean的容器根接口,给Spring 的容器定义一套规范,给IOC容器提供了一套完整的规范,负责管理Bean的生命周期、配置元数据和依赖注入。

(1)BeanFactory的主要功能包括:

  • Bean的实例化和管理:BeanFactory负责创建、初始化和管理Bean的生命周期。它会根据配置文件中定义的Bean定义来创建Bean的实例。
  • 依赖注入:BeanFactory负责解决Bean之间的依赖关系,确保每个Bean都能获取它所依赖的其他Bean。
  • 配置元数据的管理:BeanFactory会读取和管理应用程序的配置元数据,通常以XML、注解或Java配置的方式定义Bean及其属性。
  • 延迟初始化:BeanFactory支持延迟初始化,即只有在需要时才创建Bean实例。
  • AOP支持:BeanFactory支持面向切面编程(AOP),允许在Bean的生命周期中应用切面。

BeanFactory是Spring IOC容器的基础,但它通常不会直接使用,而是通过其更高级的实现来使用,如ApplicationContext
(2)BeanFactory和ApplicationContext有什么区别?
BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。

两者区别如下:

  1. 功能上的区别。BeanFactory是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。
    ApplicationContext接口作为BeanFactory的派生,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能,如继承MessageSource、支持国际化、统一的资源文件访问方式、同时加载多个配置文件等功能。

  2. 加载方式的区别。BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。

    ApplicationContext是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。 ApplicationContext启动后预载入所有的单例Bean,那么在需要的时候,不需要等待创建bean,因为它们已经创建好了。

相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢

  1. FactoryBean:是一个bean通常是用来创建比较复杂的bean,一般的bean 直接用xml配置即可,但如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,直接用xml配置比较麻烦,这时可以考虑用FactoryBean,可以隐藏实例化复杂Bean的具体的细节.

BeanFactory 和 FactoryBean区别
(1)用途:
BeanFactory是Spring IoC容器的核心接口,负责管理Bean的生命周期和依赖注入。
FactoryBean是一个特殊的Bean,充当其他Bean的工厂,用于自定义Bean的创建过程。
(2)创建对象:
BeanFactory负责创建Bean对象
FactoryBean是一个Bean,它的实例本身是一个工厂,负责创建特殊的比较复杂的Bean的对象。
(3)自定义性:
BeanFactory通常不需要自定义实现,而是由Spring框架提供的。
FactoryBean需要自定义实现,您需要编写一个类,实现FactoryBean接口,并重写getObject方法来定义Bean的创建逻辑。
(4)懒加载:
BeanFactory默认支持懒加载,直到被请求时才初始化。
FactoryBean可以通过返回代理对象来实现懒加载,它控制何时创建实际的Bean实例对象。

总结:不是所有的Bean都是由FactoryBean创建的。大多数普通的Bean由BeanFactory(或ApplicationContext)创建,而FactoryBean通常用于创建特殊类型的Bean,或者对Bean的创建过程进行自定义控制。如果您只需要普通Bean,不需要实现FactoryBean接口。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/774531.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

爬虫进阶:Selenium与Ajax的无缝集成

爬虫与Ajax的挑战 Ajax&#xff08;Asynchronous JavaScript and XML&#xff09;允许网页在不重新加载整个页面的情况下与服务器交换数据并更新部分内容。这为用户带来了更好的体验&#xff0c;但同时也使得爬虫在抓取数据时面临以下挑战&#xff1a; 动态内容加载&#xff…

【基础算法】UE中实现轮播

本期作者&#xff1a;尼克 易知微3D引擎技术负责人 当前N 总数M 从0到M-1 从1到M 感谢阅读&#xff0c;以上内容均由易知微3D引擎团队原创设计&#xff0c;以及易知微版权所有&#xff0c;转载请注明出处&#xff0c;违者必究&#xff0c;谢谢您的合作。申请转载授权后台回复【…

C++基石:掌握高效编程的艺术

C 关于命名空间&#xff1a;namespace 上述文档详细介绍了C标准库&#xff08;Standard C Library&#xff09;的一些关键约定&#xff0c;这些约定不仅帮助开发者理解如何正确使用库中的功能&#xff0c;也明确了实现者在设计库时的灵活性和限制。下面是对文档中提到的几个要点…

基于Java中的SSM框架实现物流管理系统项目【项目源码+论文说明】

基于Java中的SSM框架实现物流管理系统演示 摘要 企业的发展离不开物流的运输&#xff0c;在一个大型的企业中&#xff0c;商品的生产和建设&#xff0c;推广只是前期的一些工作&#xff0c;在后期的商品销售和物流方面的建立&#xff0c;才能让一个企业得到大力的发展。 企业…

Mysql中间件和高可用

文章目录 一、MySQL中间件代理服务器MycatMycat应用场景Mycat部署 实现读写分离 二、MySQL高可用高可用解决方案MHA高可用实现MHA 一、MySQL中间件代理服务器 数据库主要分为两大类&#xff1a;关系型数据库与 NoSQL 数据库&#xff08;非关系型数据库&#xff09;。 数据库主…

MinIO:开源对象存储解决方案的领先者

MinIO:开源对象存储解决方案的领先者 MinIO 是一款开源的对象存储系统&#xff0c;致力于提供高性能、可伸缩、安全的数据存储解决方案。 官方解释&#xff1a;MinIO 是一个基于Apache License v2。0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口&#xff0c;非常适…

vue 模糊查询加个禁止属性

vue 模糊查询加个禁止属性 父组件通过属性传&#xff0c;是否禁止输入-------默认可以输入

Quantlab5.0:一切围绕可实盘策略驱动开发

原创文章第573篇&#xff0c;专注“AI量化投资、世界运行的规律、个人成长与财富自由"。 2024年上半年即将结束&#xff0c;开始准备星球下半年的工作。 目前设想的——Quantlab5.0&#xff0c;之所以升级一个大版本&#xff0c;与4.x有很大不同。 5.0专注策略开发&…

高效任务分配的常见7步法

高效的任务分配有助于优化资源配置&#xff0c;提升开发效率与质量&#xff0c;降低成本和项目风险&#xff0c;最终提高客户满意度。如果任务分配不合理&#xff0c;可能导致资源浪费&#xff0c;造成项目延期和成本超支&#xff0c;影响工作质量&#xff0c;增加项目风险。 因…

小超市进销存软件永久免费版,免费使用!

在快节奏的商业环境中&#xff0c;小超市的管理效率直接关系到经营成本和盈利空间&#xff0c;为了帮助广大中小超市业主解决进销存管理的难题&#xff0c;象过河软件推出小超市进销存软件永久免费版&#xff0c;可让超市管理者长期免费使用。 象过河开发的小超市进销存软件专为…

谷粒商城学习-07-虚拟机网络设置

文章目录 一&#xff0c;找到配置文件Vagrantfile二&#xff0c;查询虚拟机网卡地址1&#xff0c;查看虚拟机网络配置2&#xff0c;查看宿主机网络配置 三&#xff0c;修改配置文件下的IP配置四&#xff0c;重新启动虚拟机即可生效五&#xff0c;Vagrantfile 的作用1&#xff0…

渲染农场渲染真的很贵吗?如何正确使用云渲染农场?

作为渲染行业主流的技术服务“渲染农场"&#xff0c;一直都是备受大家关注&#xff0c;渲染农场最核心的在于充足的计算机算力&#xff0c;结合3D软件支持多台机器渲染的特点&#xff0c;租用渲染农场的机器帮助你快速的解决你的渲染项目。 虽然说渲染农场需要支付一定的…

【电子数据取证】LX-A603互联网取证系统

文章关键词&#xff1a;电子数据取证、网站取证、快速固证 LX-A603可以通过简单的操作步骤&#xff0c;实现在符合规范的情况下自动对网站进行快速镜像、截屏固定、屏幕录像、生成报告等功能。满足了对互联网网站取证的实战化需求&#xff0c;极大提升工作效率。 应用场景1&a…

打包 最新血液净化器制作技术和资料

网盘 https://pan.baidu.com/s/1fm3LF20dCvy4iSMQklHpug?pwd4je2 便携可穿戴可血液净化用器件及其制备方法和应用.pdf 基于贻贝仿生化学的血液净化材料及其制备方法.pdf 膜分离式一体化血液净化系统.pdf 血液净化器固定夹.pdf 血液净化膜及其制备方法和应用.pdf 评估血液净化…

烟台LP-SCADA系统如何实现实时监控和过程控制?

关键字:LP-SCADA系统, 传感器可视化, 设备可视化, 独立SPC系统, 智能仪表系统,SPC可视化,独立SPC系统 LP-SCADA&#xff08;监控控制与数据采集&#xff09;系统实现实时监控和过程控制的主要原理和组件如下&#xff1a; 数据采集&#xff1a;LP-SCADA系统通过部署在现场的传…

STL vector 手写--迭代器设计思想、空间配置器思想!两个面试题

STL空间配置器 空间配置器的核心功能就是把对象的内存开辟和对象构造的过程分解开&#xff0c;对象析构和内存释放的过程分解开&#xff0c;因此空间配置器主要提供了以下四个函数&#xff1a; 空间配置器的函数功能allocate负责开辟内存deallocate负责释放内存construct负责…

一键直达:2024最新Win10系统安装包!快来下载!

对于想体验Win10系统最新功能的用户来说&#xff0c;寻找可靠的最新系统安装包是特别重要的。接下来系统之家小编就给大家带来2024年最新Win10系统安装包&#xff0c;有需要的小伙伴一键点击就能开始下载。该系统安装步骤简单易懂&#xff0c;无需担心任何装机经验。 推荐下载&…

快递物流运输中的RFID智能锁控应用方案

一、物流货运管理的痛点分析 1.1 货物安全与监控难题 物流货运过程中&#xff0c;货物安全是首要关注的问题。传统的锁控方式存在诸多不足&#xff0c;例如易被撬锁、监控盲点以及难以实时追踪货物状态。据统计&#xff0c;每年因货物丢失或损坏导致的经济损失高达数十亿美元…

景区智能厕所系统,打造智能化,人性化公共空间

在智慧旅游的大潮中&#xff0c;景区智能厕所系统正逐渐成为提升公共空间智能化、人性化水平的关键载体。作为智慧城市建设的重要组成部分&#xff0c;智能厕所系统不仅解决了传统公厕存在的诸多问题&#xff0c;更通过科技的力量&#xff0c;为游客创造了更加舒适、便捷的如厕…

中电金信:加快企业 AI 平台升级,构建金融智能业务新引擎

在当今数字化时代的浪潮下&#xff0c;人工智能&#xff08;AI&#xff09;技术的蓬勃发展正为各行业带来前所未有的变革与创新契机。尤其是在金融领域&#xff0c;AI 模型的广泛应用已然成为提升竞争力、优化业务流程以及实现智能化转型的关键驱动力。然而&#xff0c;企业在积…