Spring学习记录
目录
bean的单例与多例 设置
工厂模式的三种形态
简单工厂模式
代码:
运行结果:
总结:
工厂模式
代码:
运行结果:
总结:
抽象工厂模式
代码:
运行结果:
总结:
7.Bean的实例化(获取)方式
7.1 通过构造方法实例化
代码:
运行结果:
7.2 通过简单工厂模式实例化
代码:
执行结果:
7.3 通过factory-bean实例化
代码:
运行结果:
7.4 通过FactoryBean接口实例化
代码:
执行结果:
7.5 BeanFactory和FactoryBean的区别 【工作面试题!!!】
7.5.1 BeanFactory
7.5.2 FactoryBean
7.6 注入自定义Date
如以下代码:
Student
spring.xml
测试程序
运行结果:
如果把日期格式修改一下:
执行结果:
这种情况下,我们就可以使用FactoryBean来完成这个骚操作。
代码:
编写DateFactoryBean实现FactoryBean接口:
编写spring配置文件:
测试类
运行结果:
bean的单例与多例 设置
bean的单例与多例 设置 scope属性设置:默认singleton 多例:prototype
默认下:【启动容器的时候就创建对象了】
设置
scope为:prototype【启动容器的时候不会创建对象】【在调getBean才创建】
scope 还有多个值:
工厂模式的三种形态
工厂模式通常有三种形态:
- 第一种:简单工厂模式(Simple Factory):不属于23种设计模式之一。简单工厂模式又叫做:静态 工厂方法模式。简单工厂模式是工厂方法模式的一种特殊实现。
- 第二种:工厂方法模式(Factory Method):是23种设计模式之一。
- 第三种:抽象工厂模式(Abstract Factory):是23种设计模式之一。
简单工厂模式
简单工厂模式的角色包括三个:
- 抽象产品 角色
- 具体产品 角色
- 工厂类 角色
代码:
package com.dong.factory;/*** 抽象产品角色*/
public abstract class Weapon {public abstract void attack();
}
package com.dong.factory;/*** 具体产品角色*/
public class Tank extends Weapon{public void attack() {System.out.println("坦克开炮!!!!!");}
}
package com.dong.factory;/*** 具体产品角色*/
public class Warcraft extends Weapon{public void attack() {System.out.println("战斗机扔下小男孩!!!!!");}
}
package com.dong.factory;/*** 工厂类角色*/
public class WeaponFactory {public static Weapon get(String weaponType){if (weaponType==null||weaponType.trim().length()==0) {return null;}Weapon weapon=null;if ("TANK".equals(weaponType)){weapon=new Tank();} else if ("WARCRAFT".equals(weaponType)) {weapon=new Warcraft();}else {throw new RuntimeException("不⽀持该武器!");}return weapon;}
}
package com.dong.factory;/*** 客户端程序*/
public class Test {public static void main(String[] args) {Weapon weapon=WeaponFactory.get("TANK");weapon.attack();Weapon weapon1=WeaponFactory.get("WARCRAFT");weapon1.attack();}
}
运行结果:
总结:
工厂模式
工厂方法模式既保留了简单工厂模式的优点,同时又解决了简单工厂模式的缺点。
工厂方法模式的角色包括:
- 抽象工厂角色
- 具体工厂角色
- 抽象产品角色
- 具体产品角色
代码:
package com.dong.factory.method;/*** 抽象产品角色*/
public abstract class Weapon {public abstract void attack();
}
package com.dong.factory.method;/*** 具体产品角色*/
public class Dagger extends Weapon{@Overridepublic void attack() {System.out.println("炸军舰。。。。");}
}
package com.dong.factory.method;/*** 具体产品角色*/
public class Gun extends Weapon {@Overridepublic void attack() {System.out.println("开枪射击。。。。");}
}
package com.dong.factory.method;/*** 抽象⼯⼚⻆⾊*/
public abstract class WeaponFactory {public abstract Weapon get();
}
package com.dong.factory.method;/*** 具体⼯⼚⻆⾊*/
public class GunFactory extends WeaponFactory{@Overridepublic Weapon get() {return new Gun();}
}
package com.dong.factory.method;/*** 具体⼯⼚⻆⾊--生产具体产品*/
public class DaggerFactory extends WeaponFactory{@Overridepublic Weapon get() {return new Dagger();}
}
package com.dong.factory.method;/*** 客户端程序*/
public class Test {public static void main(String[] args) {WeaponFactory weaponFactory=new DaggerFactory();Weapon dagger=weaponFactory.get();dagger.attack();WeaponFactory weaponFactory1=new GunFactory();Weapon gun=weaponFactory1.get();gun.attack();}
}
运行结果:
总结:
抽象工厂模式
- 抽象工厂模式相对于工厂方法模式来说,就是工厂方法模式是针对一个产品系列的,而抽象工厂模式是针对多个产品系列的,即工厂方法模式是一个产品系列一个工厂类,而抽象工厂模式是多个产品系列一个工厂类。
- 抽象工厂模式特点:抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。它有多个抽象产品类,每个抽象产品类可以派生出多个具体产品类,一个抽象工厂类,可以派生出多个具体工厂类,每个具体工厂类可以创建多个具体产品类的实例。每一个模式都是针对一定问题的解决方案,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式针对的是多个产品等级结果。
抽象工厂中包含4个角色:
- 抽象工厂角色
- 具体工厂角色
- 抽象产品角色
- 具体产品角色
抽象工厂模式的类图如下:
抽象工厂模式代码如下:
代码:
package com.dong.product;/*** 武器产品族* @author dong* @version 1.0* @className Weapon* @since 1.0**/
public abstract class Weapon {public abstract void attack();
}
package com.dong.product;/*** 武器产品族中的产品等级1* @author dong* @version 1.0* @className Gun* @since 1.0**/
public class Gun extends Weapon{@Overridepublic void attack() {System.out.println("开枪射击!");}
}
package com.dong.product;/*** 武器产品族中的产品等级2* @author dong* @version 1.0* @className Dagger* @since 1.0**/
public class Dagger extends Weapon{@Overridepublic void attack() {System.out.println("砍丫的!");}
}
package com.dong.product;/*** 水果产品族* @author dong* @version 1.0* @className Fruit* @since 1.0**/
public abstract class Fruit {/*** 所有果实都有一个成熟周期。*/public abstract void ripeCycle();
}
package com.dong.product;/*** 水果产品族中的产品等级1* @author dong* @version 1.0* @className Orange* @since 1.0**/
public class Orange extends Fruit{@Overridepublic void ripeCycle() {System.out.println("橘子的成熟周期是10个月");}
}
package com.dong.product;/*** 水果产品族中的产品等级2* @author dong* @version 1.0* @className Apple* @since 1.0**/
public class Apple extends Fruit{@Overridepublic void ripeCycle() {System.out.println("苹果的成熟周期是8个月");}
}
package com.dong.factory;import com.dong.product.Fruit;
import com.dong.product.Weapon;/*** 抽象工厂* @author dong* @version 1.0* @className AbstractFactory* @since 1.0**/
public abstract class AbstractFactory {public abstract Weapon getWeapon(String type);public abstract Fruit getFruit(String type);
}
package com.dong.factory;import com.dong.product.Dagger;
import com.dong.product.Fruit;
import com.dong.product.Gun;
import com.dong.product.Weapon;/*** 武器族工厂* @author dong* @version 1.0* @className WeaponFactory* @since 1.0**/
public class WeaponFactory extends AbstractFactory{public Weapon getWeapon(String type){if (type == null || type.trim().length() == 0) {return null;}if ("Gun".equals(type)) {return new Gun();} else if ("Dagger".equals(type)) {return new Dagger();} else {throw new RuntimeException("无法生产该武器");}}@Overridepublic Fruit getFruit(String type) {return null;}
}
package com.dong.factory;import com.dong.product.*;/*** 水果族工厂* @author dong* @version 1.0* @className FruitFactory* @since 1.0**/
public class FruitFactory extends AbstractFactory{@Overridepublic Weapon getWeapon(String type) {return null;}public Fruit getFruit(String type){if (type == null || type.trim().length() == 0) {return null;}if ("Orange".equals(type)) {return new Orange();} else if ("Apple".equals(type)) {return new Apple();} else {throw new RuntimeException("我家果园不产这种水果");}}
}
package com.dong.client;import com.dong.factory.AbstractFactory;
import com.dong.factory.FruitFactory;
import com.dong.factory.WeaponFactory;
import com.dong.product.Fruit;
import com.dong.product.Weapon;/*** @author dong* @version 1.0* @className Client* @since 1.0**/
public class Client {public static void main(String[] args) {// 客户端调用方法时只面向AbstractFactory调用方法。AbstractFactory factory = new WeaponFactory(); // 注意:这里的new WeaponFactory()可以采用 简单工厂模式 进行隐藏。Weapon gun = factory.getWeapon("Gun");Weapon dagger = factory.getWeapon("Dagger");gun.attack();dagger.attack();AbstractFactory factory1 = new FruitFactory(); // 注意:这里的new FruitFactory()可以采用 简单工厂模式 进行隐藏。Fruit orange = factory1.getFruit("Orange");Fruit apple = factory1.getFruit("Apple");orange.ripeCycle();apple.ripeCycle();}
}
运行结果:
总结:
抽象工厂模式的优缺点:
- 优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
- 缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在AbstractFactory里加代码,又要在具体的里面加代码。
7.Bean的实例化(获取)方式
Spring为Bean提供了多种实例化方式,通常包括4种方式。(也就是说在Spring中为Bean对象的创建准备了多种方案,目的是:更加灵活)
- 第一种:通过构造方法实例化
- 第二种:通过简单工厂模式实例化
- 第三种:通过factory-bean实例化
- 第四种:通过FactoryBean接口实例化
7.1 通过构造方法实例化
- 我们之前一直使用的就是这种方式。默认情况下,会调用Bean的无参数构造方法。
代码:
先配置好各种依赖:
spring.xml【spring6的配置文件】
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd"><!--spring提供的实例化方式,第一种:在spring配置文件中总结配置类全路径,spring会自动调用该类的无参构造方法来实例化Bean--><bean id="sb" class="com.dong.spring6.bean.SpringBean"/></beans>
maven:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>li.dong</groupId><artifactId>spring6-005-bean-instantiation</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.9</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency></dependencies><properties><maven.compiler.source>19</maven.compiler.source><maven.compiler.target>19</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties></project>
package com.dong.spring6.bean;public class SpringBean {public SpringBean() {System.out.println("Spring Bean 的无参构造方法执行。。。。。");}
}
测试:
package com.dong.spring6.test;import com.dong.spring6.bean.SpringBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class BeanInstantiationTest {@Testpublic void teatInstantiation(){ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");SpringBean springBean = applicationContext.getBean("sb", SpringBean.class);System.out.println(springBean);}
}
运行结果:
7.2 通过简单工厂模式实例化
代码:
第一步:定义一个Bean
package com.dong.spring6.bean;public class Start {public Start() {System.out.println("Start 无参构造方法正在执行。。。。。");}
}
第二步:编写简单工厂模式当中的工厂类
package com.dong.spring6.bean;/*** 简单工厂模式中的工厂类角色。 星工厂*/
public class StartFactory {public static Start get(){return new Start();}
}
第三步:在Spring配置文件中指定创建该Bean的方法(使用factory-method属性指定)
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd"><!--spring提供的实例化方式,第一种:在spring配置文件中总结配置类全路径,spring会自动调用该类的无参构造方法来实例化Bean--><bean id="sb" class="com.dong.spring6.bean.SpringBean"/><!--spring提供的实例化方式,第二种:通过简单工厂模式,你需要在spring配置文件中告诉spring框架,调用哪个类的哪个方法获取Bean --><!--factory-method 属性指定的是工厂类当中的静态方法,也就是告诉spring框架,调用这个方法可以获取Bean --><bean id="start" class="com.dong.spring6.bean.StartFactory" factory-method="get"/></beans>
第四步:编写测试程序
package com.dong.spring6.test;import com.dong.spring6.bean.Start;
import com.dong.spring6.bean.StartFactory;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class BeanInstantiationTest {@Testpublic void teatInstantiation2(){ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");Start start = applicationContext.getBean("start", Start.class);System.out.println(start);}
}
teatInstantiation2
方法中的Start start = applicationContext.getBean("start", Start.class);
中,使用Start.class
参数是因为 Spring 容器返回的对象类型应该与这里指定的类型保持一致。- 虽然在
spring.xml
配置文件中 Bean 的定义指定的是StartFactory
类并配置了其静态方法get()
,但实际上 Spring 容器会调用该方法并返回一个Start
类型的实例,这个实例的类型就是由 Spring 自动推断得出的。因此,在teatInstantiation2
方法中,使用Start.class
作为参数,表示我们期望获取的是一个Start
类型的对象,而不是其他类型。
执行结果:
加载spring容器的时候会调用配置的bean的所有无参构造方法
7.3 通过factory-bean实例化
这种方式本质上是:通过工厂方法模式进行实例化。
代码:
第一步:定义一个Bean
package com.dong.spring6.bean;/*** 工厂方法模式中的具体产品角色*/
public class Gun {public Gun() {System.out.println("Gun的无参构造方法执行。。。。。。");}
}
第二步:定义具体工厂类,工厂类中定义实例方法
package com.dong.spring6.bean;/*** 工厂方法模式中的具体工厂角色*/
public class GunFactory {//工厂方法模式中的具体工厂角色中的方法是 实例化方法public Gun get(){return new Gun();}
}
第三步:在Spring配置文件中指定factory-bean以及factory-method
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd"><!--spring提供的实例化方式,第一种:在spring配置文件中总结配置类全路径,spring会自动调用该类的无参构造方法来实例化Bean--><bean id="sb" class="com.dong.spring6.bean.SpringBean"/><!--spring提供的实例化方式,第二种:通过简单工厂模式,你需要在spring配置文件中告诉spring框架,调用哪个类的哪个方法获取Bean --><!--factory-method 属性指定的是工厂类当中的静态方法,也就是告诉spring框架,调用这个方法可以获取Bean --><bean id="start" class="com.dong.spring6.bean.StartFactory" factory-method="get"/><!--spring提供的实例化方式,第三种:通过工厂方法模式,通过factory-bean属性+factory-method属性共同来完成。--><!--告诉spring框架,调用哪个对象的哪个方法来获取Bean--><bean id="gunFactory" class="com.dong.spring6.bean.GunFactory"/><!--以下配置很关键,factory-bean属性告诉spring调用哪个对象 factory-method属性告诉spring调用该对象的哪个方法。 --><bean id="gun" factory-bean="gunFactory" factory-method="get"/>
</beans>
第四步:编写测试程序
package com.dong.spring6.test;import com.dong.spring6.bean.Gun;
import com.dong.spring6.bean.SpringBean;
import com.dong.spring6.bean.Start;
import com.dong.spring6.bean.StartFactory;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class BeanInstantiationTest {@Testpublic void teatInstantiation(){ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");SpringBean springBean = applicationContext.getBean("sb", SpringBean.class);System.out.println(springBean);}@Testpublic void teatInstantiation2(){ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");Start start = applicationContext.getBean("start", Start.class);System.out.println(start);}@Testpublic void teatInstantiation3(){ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");Gun gun = applicationContext.getBean("gun", Gun.class);System.out.println(gun);}
}
运行结果:
7.4 通过FactoryBean接口实例化
- 以上的第三种方式中,factory-bean是我们自定义的,factory-method也是我们自己定义的。
- 在Spring中,当你编写的类直接实现FactoryBean接口之后,factory-bean不需要指定了,factory-method也不需要指定了。
- factory-bean会自动指向实现FactoryBean接口的类,factory-method会自动指向getObject()方法。
代码:
第一步:定义一个Bean
package com.dong.spring6.bean;/*** Bean*/
public class Person {public Person() {System.out.println("Person无参构造执行。。。。。");}
}
第二步:编写一个类实现FactoryBean接口
package com.dong.spring6.bean;import org.springframework.beans.factory.FactoryBean;public class PersonFactoryBean implements FactoryBean<Person> {@Overridepublic Person getObject() throws Exception {return new Person();}@Overridepublic Class<?> getObjectType() {return null;}/*** 这个方法在接口中有默认实现。* 默认返回true,表示单例的* 如果想多例,总结总结将这个方法的返回 修改为 return false;即可* @return*/@Overridepublic boolean isSingleton() {return FactoryBean.super.isSingleton();}
}
第三步:在Spring配置文件中配置FactoryBean
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd"><!--spring提供的实例化方式,第一种:在spring配置文件中总结配置类全路径,spring会自动调用该类的无参构造方法来实例化Bean--><bean id="sb" class="com.dong.spring6.bean.SpringBean"/><!--spring提供的实例化方式,第二种:通过简单工厂模式,你需要在spring配置文件中告诉spring框架,调用哪个类的哪个方法获取Bean --><!--factory-method 属性指定的是工厂类当中的静态方法,也就是告诉spring框架,调用这个方法可以获取Bean --><bean id="start" class="com.dong.spring6.bean.StartFactory" factory-method="get"/><!--spring提供的实例化方式,第三种:通过工厂方法模式,通过factory-bean属性+factory-method属性共同来完成。--><!--告诉spring框架,调用哪个对象的哪个方法来获取Bean--><bean id="gunFactory" class="com.dong.spring6.bean.GunFactory"/><!--以下配置很关键,factory-bean属性告诉spring调用哪个对象 factory-method属性告诉spring调用该对象的哪个方法。 --><bean id="gun" factory-bean="gunFactory" factory-method="get"/><!--spring提供的实例化方式,第四种 :通过FactoryBean接口来实现。 --><!--这种方式实际上是第三种方式的简化。--><!--由于你编写的类实现了FactoryBean接口,所以这个类是一个特殊的类,不需要你再手动指定:factory-bean、factory-method--><!--通过一个特殊的Bean:工厂Bean,来返回一个普通的Bean Person对象--><!--通过FactoryBean这个工厂Bean主要是想对普通Bean进行加工处理。--><bean id="person" class="com.dong.spring6.bean.PersonFactoryBean"/></beans>
测试程序:
package com.dong.spring6.test;import com.dong.spring6.bean.*;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class BeanInstantiationTest {@Testpublic void teatInstantiation(){ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");SpringBean springBean = applicationContext.getBean("sb", SpringBean.class);System.out.println(springBean);}@Testpublic void teatInstantiation2(){ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");Start start = applicationContext.getBean("start", Start.class);System.out.println(start);}@Testpublic void teatInstantiation3(){ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");Gun gun = applicationContext.getBean("gun", Gun.class);System.out.println(gun);}@Testpublic void teatInstantiation4(){ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");Person person = applicationContext.getBean("person", Person.class);System.out.println(person);}
}
执行结果:
FactoryBean在Spring中是一个接口。被称为“工厂Bean”。“工厂Bean”是一种特殊的Bean。所有的“工厂Bean”都是用来协助Spring框架来创建其他Bean对象的。
7.5 BeanFactory和FactoryBean的区别 【工作面试题!!!】
7.5.1 BeanFactory
- Spring IoC容器的顶级对象,BeanFactory被翻译为“Bean工厂”,在Spring的IoC容器中,“Bean工厂”负责创建Bean对象。
- BeanFactory是工厂。
7.5.2 FactoryBean
FactoryBean:它是一个Bean,是一个能够辅助Spring实例化其它Bean对象的一个Bean。
在Spring中,Bean可以分为两类:
- 第一类:普通Bean
- 第二类:工厂Bean(记住:工厂Bean也是一种Bean,只不过这种Bean比较特殊,它可以辅助Spring实例化其它Bean对象。)
7.6 注入自定义Date
我们前面说过,java.util.Date在Spring中被当做简单类型,简单类型在注入的时候可以直接使用value属性或value标签来完成。但我们之前已经测试过了,对于Date类型来说,采用value属性或value标签赋值的时候,对日期字符串的格式要求非常严格,必须是这种格式的:Mon Oct 10 14:30:26 CST 2022。其他格式是不会被识别的。
如以下代码:
Student
package com.dong.spring6.bean;import java.util.Date;/*** @author dong* @version 1.0* @className Student* @since 1.0**/
public class Student {private Date birth;public void setBirth(Date birth) {this.birth = birth;}@Overridepublic String toString() {return "Student{" +"birth=" + birth +'}';}
}
spring.xml
<bean id="studentBean" class="com.dong.spring6.bean.Student"><property name="birth" value="Mon Oct 10 14:30:26 CST 2002"/>
</bean>
测试程序
@Test
public void testDate(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");Student studentBean = applicationContext.getBean("studentBean", Student.class);System.out.println(studentBean);
}
运行结果:
如果把日期格式修改一下:
<bean id="studentBean" class="com.dong.spring6.bean.Student"><property name="birth" value="2002-10-10"/>
</bean>
执行结果:
这种情况下,我们就可以使用FactoryBean来完成这个骚操作。
代码:
package com.dong.spring6.bean;import java.util.Date;public class Student {private Date birth;public void setBirth(Date birth) {this.birth = birth;}@Overridepublic String toString() {return "Student{" +"birth=" + birth +'}';}
}
编写DateFactoryBean实现FactoryBean接口:
package com.dong.spring6.bean;import org.springframework.beans.factory.FactoryBean;import java.text.SimpleDateFormat;
import java.util.Date;public class DateFactoryBean implements FactoryBean<Date> {private String strDate;public DateFactoryBean(String strDate) {this.strDate = strDate;}@Overridepublic Date getObject() throws Exception {SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");Date date = simpleDateFormat.parse(strDate);return date;}@Overridepublic Class<?> getObjectType() {return null;}
}
编写spring配置文件:
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd"><!--通过工厂Bean:DateFactoryBean 来返回普通Bean :java.util.Date--><bean id="dateFactoryBean" class="com.dong.spring6.bean.DateFactoryBean"><constructor-arg index="0" value="2002-07-01"/></bean><bean id="studentBean" class="com.dong.spring6.bean.Student"><property name="birth" ref="dateFactoryBean"/></bean><!--spring提供的实例化方式,第一种:在spring配置文件中总结配置类全路径,spring会自动调用该类的无参构造方法来实例化Bean--><bean id="sb" class="com.dong.spring6.bean.SpringBean"/><!--spring提供的实例化方式,第二种:通过简单工厂模式,你需要在spring配置文件中告诉spring框架,调用哪个类的哪个方法获取Bean --><!--factory-method 属性指定的是工厂类当中的静态方法,也就是告诉spring框架,调用这个方法可以获取Bean --><bean id="start" class="com.dong.spring6.bean.StartFactory" factory-method="get"/><!--spring提供的实例化方式,第三种:通过工厂方法模式,通过factory-bean属性+factory-method属性共同来完成。--><!--告诉spring框架,调用哪个对象的哪个方法来获取Bean--><bean id="gunFactory" class="com.dong.spring6.bean.GunFactory"/><!--以下配置很关键,factory-bean属性告诉spring调用哪个对象 factory-method属性告诉spring调用该对象的哪个方法。 --><bean id="gun" factory-bean="gunFactory" factory-method="get"/><!--spring提供的实例化方式,第四种 :通过FactoryBean接口来实现。 --><!--这种方式实际上是第三种方式的简化。--><!--由于你编写的类实现了FactoryBean接口,所以这个类是一个特殊的类,不需要你再手动指定:factory-bean、factory-method--><!--通过一个特殊的Bean:工厂Bean,来返回一个普通的Bean Person对象--><!--通过FactoryBean这个工厂Bean主要是想对普通Bean进行加工处理。--><bean id="person" class="com.dong.spring6.bean.PersonFactoryBean"/></beans>
测试类
package com.dong.spring6.test;import com.dong.spring6.bean.*;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class BeanInstantiationTest {@Testpublic void testDate(){ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");Student student= applicationContext.getBean("studentBean", Student.class);System.out.println(student);}
}
运行结果:
想要输出日期格式为Student{birth=2002-07-01}
改进如下:
在
DateFactoryBean
类的getObject()
方法中,你可以将SimpleDateFormat
的格式字符串中表示月份的MM
修改为小写的mm
。此外,为了让喜欢阅读时间戳的人不用再看毫秒和时区信息,可以使用另一个SimpleDateFormat
对象对日期进行格式化,并返回格式化后的字符串。修改后的
DateFactoryBean
类如下所示:
public class DateFactoryBean implements FactoryBean<Date> {private String strDate;public DateFactoryBean(String strDate) {this.strDate = strDate;}@Overridepublic Date getObject() throws Exception {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");return sdf.parse(strDate);}@Overridepublic Class<?> getObjectType() {return Date.class;}@Overridepublic String toString() {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");return sdf.format(getObject());}
}
然后在
Student
类的toString()
方法中,调用DateFactoryBean
对象的toString()
方法,以获得格式化后的日期字符串。修改后的Student
类如下所示:
public class Student {private Date birth;public void setBirth(Date birth) {this.birth = birth;}@Overridepublic String toString() {return "Student{" +"birth=" + new DateFactoryBean(birth.toString()) +'}';}
}
这样,在 BeanInstantiationTest
测试类运行后,输出的就是 Student{birth=2002-07-01}
了。
或:
可以使用
SimpleDateFormat
,将birth
格式化成指定格式的字符串,然后输出这个字符串。修改后的Student
类如下所示:
public class Student {private Date birth;public void setBirth(Date birth) {this.birth = birth;}@Overridepublic String toString() {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");String birthStr = sdf.format(birth);return "Student{" +"birth=" + birthStr +'}';}
}
【注意:
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");
】 这里的格式:yyyy-MM-dd 月份要大写!!
Student.java 类
package com.dong.spring6.bean;import java.text.SimpleDateFormat;
import java.util.Date;public class Student {private Date birth;public void setBirth(Date birth) {this.birth = birth;}@Overridepublic String toString() {SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");String birthStr=simpleDateFormat.format(birth);return "Student{" +"birth=" + birthStr +'}';}
}
改进后运行结果:
相关文章:

Spring学习记录
目录 bean的单例与多例 设置 工厂模式的三种形态 简单工厂模式 代码: 运行结果: 总结: 工厂模式 代码: 运行结果: 总结: 抽象工厂模式 代码: 运行结果: 总结: …...
模板方法-
定义:又叫模板模式,是指定义一个算法骨架,并允许子类为其中的一个或多个步骤提供实现。 适用场景: 1、一次性实现一个算法不变的部分,并将可变的行为留给子类来实现 2、各子类中公共的行为被提取出来并集中到一个公共的父类中,从而避免代码重复 优点…...

[Kubernetes] - RabbitMQ学习
1.消息队列 消息: 在应用间传送的数据队列,先进先出 1.2. 作用 好处:解耦, 容错,削峰坏处:降低系统可用性,系统复杂度提高,一致性问题; RabbitMQ组成部分:…...

swagger页面 doc.html出不来,swagger-ui/index.html能出来
swagger页面 doc.html出不来,swagger-ui/index.html能出来。前前后后折腾了很久,jar包冲突,jar包版本,添加路径啥的都弄了,就是出不来。 后来全局搜索“doc.html”页面发现能出来的项目能搜到这个页面: 定…...

IEEE802.3和IEEE802.11的分类(仅为分类)
IEEE802.3标准 IEEE802.3:10兆以太网 ●10Base-5 使用粗同轴电缆,最大网段长度为500m,基带传输方法; ●10Base-2 使用细同轴电缆,最大网段长度为185m,基带传输方法; ●10Base&am…...
c# cad二次开发通过获取excel数据 在CAD绘图,将CAD属性导出到excel
c# cad二次开发通过获取excel数据 在CAD绘图,将CAD属性导出到excel using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Runtime; using System; using System.Collections.Generic; using System.Linq; us…...
LLM之高性能向量检索库
LLM向量数据库 高性能向量检索库milvus简介安装调用 faiss简介安装调用 高性能向量检索库 milvus 简介 Milvus 是一个开源的向量数据库引擎,旨在提供高效的向量存储、检索和分析能力。它被设计用于处理大规模的高维向量数据,常用于机器学习、计算机视觉…...
实体类注解
目录 一、TableField注解 二、TableId注解 三、Table注解 四、TableLogic注解 五、Getter与Setter注解 六、EqualsAndHashCode注解 七、Accessors注解 一、TableField注解 Data NoArgsConstructor //空参构造方法 AllArgsConstructor //全参构造方法 TableName("t…...
常见数据结构种类
常见数据结构种类 数据存储的常用结构有:栈、队列、数组、链表和红黑树 a.队列(queue) – 先进先出,后进后出。 – 场景:各种排队。叫号系统。 – 有很多集合可以实现队列。 b.栈(stack) – …...

linux高级---k8s中的五种控制器
文章目录 一、k8s的控制器类型二、pod与控制器之间的关系三、状态与无状态化对特点四、Deployment1、Deployment的资源清单文件2、在配置清单中调用deployment控制器3、镜像更新4、金丝雀发布5、删除Deployment 五、Statefulset六、DaemonSet1、daemonset的资源清单文件2、在配…...

记一次udp服务性能优化经历
目录 概述磁盘io网络io减少重复计算减少内存复制减少互斥锁 概述 手上有个go项目,接收udp信息(主要是syslog和snmp trap)并查询设备信息,将信息结构化(设备ip名称,匹配了什么规则之类的)后发送…...
uniapp和VueI18n多语言H5项目语言国际化功能搭建流程
uniapp多语言项目国家化功能搭建流程 说明:uniapp多语言项目功能搭建分为应用部分和框架部分。 应用部分,即开发者自己的代码里涉及的界面部分的语言翻译。框架部分,即uni-app内置组件和API涉及界面的部分的语言翻译。 功能的搭建是需要un…...

C# | 凸包算法之Jarvis,寻找一组点的边界/轮廓
C#实现凸包算法之Jarvis 文章目录 C#实现凸包算法之Jarvis前言示例代码实现思路测试结果结束语 前言 这篇关于凸包算法的文章,本文使用C#和Jarvis算法来实现凸包算法。 首先消除两个最基本的问题: 什么是凸包呢? 凸包是一个包围一组点的凸多…...

SpringBoot接收请求参数的方式
【方式一】原始方式 因为SpringBoot封装了Servlet,所以也允许使用HttpServletRequest类中的方法来获取 /*** 【方式一】原始方式*/RequestMapping("/demo01")public String demo01(HttpServletRequest request) {// 参数名要与页面提交的参数名一致Strin…...

MKS SERVO4257D 闭环步进电机_系列5 CAN指令说明
第1部分 产品介绍 MKS SERVO 28D/35D/42D/57D 系列闭环步进电机是创客基地为满足市场需求而自主研发的一款产品。具备脉冲接口和RS485/CAN串行接口,支持MODBUS-RTU通讯协议,内置高效FOC矢量算法,采用高精度编码器,通过位置反馈&am…...

安捷伦E4440A(Agilent) e4440a 3HZ-26.5G频谱分析仪
Agilent E4440A、Keysight E4440A、HP E4440A频谱分析仪,3 Hz - 26.5 GHz(PSA 系列) Agilent / Keysight PSA 系列 E4440A 高性能频谱分析仪提供强大的一键式测量、多功能功能集和前沿技术,可满足您的项目和需求。选项可供您选…...
华为OD机试真题 Java 实现【最长子字符串的长度】【2022Q4 100分】,附详细解题思路
一、题目描述 给你一个字符串s,字符串s首尾相连组成一个环形,请你在环形中找出‘o’字符出现了偶数次最长子字符串的长度。 二、输入描述 输入一串小写字母组成的字符串。 三、输出描述 输出一个整数。 四、解题思路 题目要求在给定的环形字符串中找出字符’o’出现了…...

【iOS】--对象的底层结构
源码 先转一下源码 //#import <Foundation/Foundation.h> #import <objc/runtime.h>interface LGPerson : NSObject property (nonatomic, strong) NSString *KCName; endimplementation LGPersonendint main(int argc, const char * argv[]) {autoreleasepool {…...
高并发内存池设计_内存池
高并发内存池设计 1. 常用的内存操作函数2. 高性能内存池设计_弊端解决之道弊端一弊端二弊端三弊端四3. 弊端解决之道内存管理维度分析内存管理组件选型4. 高并发内存管理最佳实践内存池技术内存池如何解决弊端?高并发时内存池如何实现?5. 高效内存池设计和实现实现思路 (分而…...

给编程初学者的一封信
提醒:以下内容仅做参考,具体请自行设计。 随着信息技术的快速发展,编程已经成为一个越来越重要的技能。那么,我们该如何入门编程呢?欢迎大家积极讨论 一、自学编程需要注意什么? 要有足够的时间、精力等…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...

Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...
React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构
React 实战项目:微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇!在前 29 篇文章中,我们从 React 的基础概念逐步深入到高级技巧,涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...