当前位置: 首页 > 后端技术 > Java

五、Spring创建复杂对象和对象的次数

时间:2023-04-01 15:17:36 Java

1.什么是复杂对象?复杂对象:指不能直接通过new构造方法创建的对象,简单对象是指可以通过new构造方法直接创建的对象。那么这些复杂的对象是什么?比如我们比较熟悉的Mybatis中SqlSessionFactory、Connection对象等简单对象的创建,就比较容易理解。spring应该也好办,那么复杂的对象呢?如果复杂对象Spring也能做到,那Spring就牛逼了。2.Spring工厂中创建复杂对象的三种方法2.1实现FactoryBean接口当我们实现FactoryBean接口时,那么我们就要重写这三个方法,对应的三个方法如下1.publicObjectgetObject()这个方法用于编写创建复杂对象的代码,并将复杂对象作为方法的返回值返回方法?这是因为创建每个复杂对象的代码可能不一样,所以需要我们自己改写来创建2.publicClassgetObjectType()该方法用于返回复杂对象的Class对象3.publicbooleanisSingleton()返回true表示该对象只需要创建一次,返回false表示每次调用都需要创建一个新的复杂对象。2.2以创建Connection对象为例,其实现的第一步如下所示:引入mysql相关依赖mysqlmysql-connector-java5.1.48第二步:新建类实现FactoryBean接口,重写其三个方法publicclassConnectionBeanFactoryimplementsFactoryBean{@OverridepublicConnectiongetObject()吨hrows异常{Class.forName("com.mysql.jdbc.Driver");//注意:如果是mysql8.0以上,那么需要在连接url中加入相应的时区参数Connectionconn=DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root",“行政”);返回康恩;}@OverridepublicClassgetObjectType(){returnConnection.class;}@OverridepublicbooleanisSingleton(){返回false;}}第三步:配置Spring配置文件注意:如果Class中指定的类型是FactoryBean的实现类,那么调用ConnectionBeanFactory方法中重写的getObject()方法得到的对象就是调用ConnectionBeanFactory方法创建的对象。问题:如果我只是想创建这个ConnectionBeanFactory对象如何创建?答:我们只需要在代码层面加上“&”即可。示例如下:ClassPathXmlApplicationContextctx=newClassPathXmlApplicationContext("/applicationContext.xml");ConnectionBeanFactoryconn=(ConnectionBeanFactory)ctx.getBean("&conn");System.out.println("conn="+conn);2.3关于isSingleton()方法,如果返回true,只会创建一个对象,也就是我们所谓的单例,如果为false,那么每次调用getBean()方法,都会创建一个对象,这是多个实例;根据这个特性决定是返回true(SqlSessionFactory)还是false(Connection)。为什么Connection对象是单例?这是因为每获取一个Connection对象,就相当于开启了一个事务。显然,共享这个对象会导致事务提交的混乱,彻底打乱事务的隔离特性。2.4如果涉及高版本MySQL创建连接,需要指定不使用SSL证书解决warn问题。配置如下url="jdbc:mysql://localhost:3306/suns?userSSL=false"备注:如果涉及到mysql8.x版本,还必须设置对应的时区,这个配置可以优化by百度2.5四元码。我们可以看到,以上四个要素是在代码层面写在代码上的。这其实是一种耦合的情况,所以我们可以使用Spring的配置文件来优化一下。属性注入,改写如下2.5.1在代码层面定义相应的成员变量,并提供相应的setter和getter方法publicclassConnectionBeanFactoryimplementsFactoryBean{//定义相应的四元素privateStringdriverClassName;私人字符串网址;私有字符串用户名;私有字符串密码;publicvoidsetDriverClassName(StringdriverClassName){this.driverClassName=driverClassName;}publicvoidsetUrl(Stringurl){this.url=url;}publicvoidsetUsername(Stringusername){this.username=username;}publicvoidsetPassword(Stringpassword){this.password=password;}publicStringgetDriverClassName(){returndriverClassName;}publicStringgetUrl(){返回网址;}publicStringgetUsername(){返回用户名;}publicStringgetPassword(){返回密码;}@OverridepublicConnectiongetObject()throwsException{Class.forName(driverClassName);//注意:如果是mysql8.0以上,那么还需要在连接url处添加相应的时区参数Connectionconn=DriverManager.getConnection(url,username,password);System.out.println("创建连接bean......");返回康恩;}@OverridepublicClassgetObjectType(){returnConnection.class;}@OverridepublicbooleanisSingleton(){返回真;}}2.5.2在Spring配置文件2.5.3依赖注入(DI)体验通过上面的配置,充分发挥了Spring属性注入的精髓,优点是解耦好,如果哪天觉得配置的信息不适合自己,那么我就可以直接修改配置文件来实现效果3.FactoryBean的实现原理(简易版)在java编程系统中,很多开源框架都使用了反射和接口回调,所以江湖说:接口加反射,万物皆可done.需要思考以下几个问题1>为什么Spring规定实现FactoryBean接口,通过getObject()方法获取对应的复杂对象?2>为什么ctx.getBean("conn")获取的是复杂对象Connection而不是自身的ConnectionFactoryBean?Spring内部运行流程1>通过ctx.getBean("conn")获取ConnectionFactoryBean对象,然后通过instanceOf()判断是否是FactoryBean接口的实现类2>如果是FactoryBean接口的实现类,Spring将调用其OverriddengetObject()方法来创建Connectionobject3>finallyreturntheConnectionobject4.FactoryBean总结了Spring中创建复杂对象的一种方式,也是Spring原生提供的。它在与其他框架的集成中使用了大量的FactoryBean5.实例工厂5.1为什么需要实例工厂?1>在没有Spring的基础上(也就是没有FactoryBean接口),我们需要一个工厂来生成复杂的对象。如果有一天不用Spring,我们也可以有这个工厂来生产对象。2>属于遗留工厂类,Spring也可以与