Spring笔记
通过构造器来创建bean对象
有name的创建
<bean id="person1" class="com.yxm.entity.Person">
<!-- 构造器有多少个需要传入的值就传多少个 -->
<!-- public Person(String name, String gender,Integer age) -->
<constructor-arg name="name" value="test01"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="gender" value="男"></constructor-arg>
</bean>
没有name的创建
可以没有name,但是前提是必须和你要的构造器的参数一一对应,或者说你可以使用constructor-arg标签的index属性
<bean id="person2" class="com.yxm.entity.Person">
<!-- 构造器有多少个需要传入的值就传多少个 -->
<!-- public Person(String name, String gender,Integer age) -->
<constructor-arg value="test01"></constructor-arg>
<constructor-arg value="男" index="1"></constructor-arg>
<constructor-arg value="18"></constructor-arg>
</bean>
这个时候要是出现两个重载的构造器,然后你又不想用name的话,那就用上constructor-arg标签的type属性来区分吧
<bean id="person3" class="com.yxm.entity.Person">
<!-- 构造器有多少个需要传入的值就传多少个 -->
<!-- public Person(String name, String gender) -->
<!-- public Person(String name, Integer age) -->
<constructor-arg value="test01"></constructor-arg>
<constructor-arg value="男" type="java.lang.String"></constructor-arg>
</bean>
最好还是用name吧,看着都舒服
通过p名称空间为bean属性赋值
给我的感觉是,没啥感觉,就是简化了代码,如果属性多了用这个赋值感觉很不美观,但是可以作为了解
首先来引入p名称空间
如果你是用sts插件来创建的spring的配置文件的话
点击,以后会出现如下界面
点击,然后会发现多了红线这行代码(util那行代码是后面用到的)
如果不是的话,那么就直接把红线那部分代码复制到图中位置
xmlns:p=“http://www.springframework.org/schema/p”
然后就是使用了
<!--这里就是为age属性赋值了-->
<bean id="person4" class="com.yxm.entity.Person" p:age="12"></bean>
正确为各种属性赋值
使用null值
<property name="name">
<!-- 复杂类型的赋值 -->
<null/>
</property>
引用类型赋值(引用其他bean,使用内部bean)
引用其他bean
<!-- 被引用的bean对象 -->
<bean id="car1" class="com.yxm.entity.Car">
<property name="carName" value="路虎"></property>
<property name="color" value="黑色"></property>
<property name="price" value="3000000"></property>
</bean>
<!-- 属性ref的意思是引用,所以它和容器里面取出来的car对象是一致的-->
<!--所以你变它变--!>
<property name="car" ref="car1"></property>
<!--或者<property name="car"><ref bean="car1"/> </property>--!>
使用内部bean(仅供内部使用,就算你对这个bean赋予id属性还是没什么用)
<!-- 引用内部的bean对象,就是相当于创建一个new car对象然后赋值给属性 -->
<property name="car">
<bean class="com.yxm.entity.Car">
<property name="carName" value="路虎"></property>
<property name="color" value="蓝色"></property>
<property name="price" value="3000000"></property>
</bean>
</property>
集合类型赋值(list,map,properties)
<!-- 测试集合类型的变量赋值 -->
<bean id="book1" class="com.yxm.entity.Book" p:bookName="东游记"></bean>
<!-- 为list类型的变量赋值 -->
<property name="books">
<!-- 就相当于是list=new ArrayList<>() -->
<list>
<bean id="book1" class="com.yxm.entity.Book" p:bookName="西游记"></bean>
<ref bean="book1"/>
</list>
</property>
<!-- 为map类型的变量赋值 -->
<property name="map">
<!-- 相当于是为这个变量赋值map = new LinkedHashMap<>() -->
<map>
<!-- 表示一个键值对 注意我这边使用的是Map<String,Object> -->
<entry key="key01" value="普通"></entry>
<entry key="key01" value="123"></entry>
<entry key="key02" value-ref="book1"></entry>
<entry key="key03">
<bean class="com.yxm.entity.Car" p:carName="路虎"></bean>
</entry>
<!-- <entry key-ref="" value-type=""></entry> -->
<!-- 当然entry里面还是可以嵌套其他的复杂类型变量的 -->
</map>
</property>
<!-- 为Properties类型的变量赋值 -->
<property name="properties">
<!-- 相当于赋值new Properties()-->
<props>
<!-- 因为properties 的键值对都是String类型的,所以prop标签没有value属性 -->
<prop key="username">root</prop>
</props>
</property>
util名称空间创建集合类型的bean
和p名称空间导入方式相同,选中util即可,若不是sts插件则
xmlns:util=“http://www.springframework.org/schema/util”
<!-- util名称空间创建集合类型的bean -->
<!-- 就是能够创建类似于bean的对象,当然这些对象是list map set等等 -->
<!-- 这个也可以在内部使用,也就是意味着内部的也能够在其他的bean中调用 -->
<util:map id="map1" map-class="java.util.HashMap">
<!-- 直接添加元素即可 -->
<entry key="key01" value="普通"></entry>
<entry key="key01" value="123"></entry>
<entry key="key02" value-ref="book1"></entry>
<entry key="key03">
<bean class="com.yxm.entity.Car" p:carName="路虎"></bean>
</entry>
</util:map>
<!-- 测试util名称空间 -->
<property name="map" ref="map1">
</property>
级联属性(属性的属性)赋值
关键在于property这个标签的name属性上面
<!-- 级联属性(属性的属性)赋值 -->
<bean id="person8" class="com.yxm.entity.Person">
<property name="car" ref="car1"></property>
<!-- 现在是修改赋值进行的值,比如修改车的价格 -->
<!-- 需要注意的是这边修改的话因为car是ref的缘故就会导致ref引用的那个对象也会发生改变 -->
<property name="car.price" value="90000000"></property>
</bean>
通过继承实现bean配置信息的重用和生成一个只能是配置文件内部调用的bean对象,不能够被getBean获取
bean标签的属性parent,就是指定当前bean的配置信息继承于那个 和 bean标签的属性abstract="true
<!-- 通过bean标签的parent进行实现,构造器也是可以的,而且下方这种person10有person9和person1的配置属性 -->
<!-- 可以有一个专门只供xml内部使用的bean对象,也就是在外面的getBean是获得不到的,bean标签的abstract属性-->
<bean id="person9" class="com.yxm.entity.Person" parent="person1" abstract="true">
<property name="age" value="13"></property>
</bean>
<bean id="person10" class="com.yxm.entity.Person" parent="person9">
<property name="gender" value="男"></property>
</bean>
bean之间的依赖(单纯的改变bean的创建的先后顺序)
这个作为了解就好一般用不到,貌似--------bean标签的depends-on="",里面写其他的beanid,多个的话用逗号隔开
<!-- bean标签的depend-on属性能够决定在实现当前的bean对象的之前会先创建哪一个或者几个bean对象 -->
<!--这个就表示当前的bean对象是在person9 person10 后生成--!>
<!-- <bean depends-on="person9,person10"></bean> -->
bean的作用域
取决于bean标签的scope属性
<!--
prototype:多实例,只有在你需要 它的时候容器才会进行创建并且每次创建出来的bean实例都是不同的
singleton:单实例,是bean标签的默认值,是在容器创建的时候已经生成的,并且获取的时候都是已经创建好的那个
request:在web环境下,同一次请求创建一个bean对象(一般不使用)
session:在web环境下,同一次会话创建一个bean对象(一般不使用)
-->
<bean id="car3" class="com.yxm.entity.Car"></bean>
<bean id="car2" class="com.yxm.entity.Car" scope="prototype"></bean>
//测试多实例
Car car01 = ac.getBean("car2",Car.class);
Car car02 = ac.getBean("car2",Car.class);
System.out.println(car01 == car02);
结果:false(单实例测试类似,返回true)
静态,实例工厂方法创建bean
bean的默认创建就是框架利用反射new出来的bean实例
工厂模式:工厂帮我们创建对象,也就是有一个专门帮我们创建对象的类这个类就是工厂
静态工厂:工厂本身不用创建对象,通过静态方法调用,对象 = 工厂类.工厂方法名();
实例工厂:工厂本身需要创建对象,工厂类 工厂对象 = new工厂类();工厂对象.获取对象的方法名();
静态工厂的创建
首先创建一个静态工厂类,里面有获取Car类的方法,然后再spring的配置文件中进行相关配置
//Car类的静态工厂
public class CarStaticFactory {
public static Car getInstance(String carName) {
Car car = new Car();
car.setCarName(carName);
car.setColor("蓝色");
car.setPrice(5000000);
return car;
}
}
//spring配置文件
<!-- 静态工厂创建需要的bean对象 factory-method就是获取对象的方法-->
<bean id="car4" class="com.yxm.factory.CarStaticFactory" factory-method="getInstance">
<!-- 需要下面的标签来传递参数 -->
<!-- 因为只有一个参数,所以就不写name了 -->
<constructor-arg value="路虎"></constructor-arg>
</bean>
然后调用getBean方法就行了
实例工厂的创建
先创建一个实例工厂的类对象,然后在spring配置文件中进行相应的配置
//Car类的实例工厂
public class CarInstanceFactory {
public Car getInstance(String carName) {
Car car = new Car();
car.setCarName(carName);
car.setColor("蓝色");
car.setPrice(5000000);
return car;
}
}
//Spring配置文件
<!-- 实例工厂创建需要的bean对象
先创建实例工厂所对应的bean对象,然后就是类似于静态工厂获取的形式,只是多了一个属性factory-bean
-->
<bean id="carFactory" class="com.yxm.factory.CarInstanceFactory"></bean>
<bean id="car5" class="com.yxm.entity.Car" factory-bean="carFactory" factory-method="getInstance">
<!-- 传入参数 -->
<constructor-arg value="宝马"></constructor-arg>
</bean>
调用getBean方法即可
FactoryBean来进行创建对象实例
可以理解为spring自带的工厂接口
先创建一个工厂类实现这个接口,并且实现里面的三个抽象方法,然后还是在spring的配置文件中配置就好
public class MyFactoryBeanImpl implements FactoryBean<Car>{
//如果配置文件中创建的是这个bean实例会自动调用这个方法来获取你所需要的对象实例
@Override
public Car getObject() throws Exception {
// TODO 自动生成的方法存根
System.out.println("MyFactoryBeanImpl.getObject()");
Car car = new Car();
car.setCarName("路虎");
car.setColor("红色");
car.setPrice(5000000);
return car;
}
//返回创建的实例对象的类型,Spring会自动进行调用来确定调用的是什么类型
@Override
public Class<?> getObjectType() {
// TODO 自动生成的方法存根
System.out.println("MyFactoryBeanImpl.getObjectType()");
return Car.class;
}
//是单例?
@Override
public boolean isSingleton() {
// TODO 自动生成的方法存根
System.out.println("MyFactoryBeanImpl.isSingleton()");
return false;
}
}
//spring配置文件
<!-- factoryBean来进行创建对象实例 -->
<!-- factoryBean所创建的对象实例都是在你调用getBean的方法的时候才会去创建的,无论是单实例还是多实例
也与接口所对应的方法中的是否为单实例的方法无关,这个方法只是能让你获取到的对象是单还是多
-->
<bean id="myFactoryBean" class="com.yxm.factory.MyFactoryBeanImpl"></bean>
然后调用getBean即可
这个方法一般都是在进行复杂类型的bean对象实例的时候会用到,比如那些和spring整合的时候,如SQLSessionFactory(知乎上看到的)
然后我有对这三个方法测试了一下
Car car3 = ac.getBean("myFactoryBean",Car.class);
Car car4 = ac.getBean("myFactoryBean",Car.class);
System.out.println(car3 == car4);
结果
MyFactoryBeanImpl.isSingleton()
MyFactoryBeanImpl.isSingleton()
MyFactoryBeanImpl.getObject()
car创建
MyFactoryBeanImpl.isSingleton()
MyFactoryBeanImpl.getObject()
car创建
false
isSingleton这个方法测试过,你只要加载了那个配置文件就会调用。
而getObject是在你调用getBean的时候调用。
FactoryBean的方法getObjectType()不知道是什么时候调用的,很迷,就算我写它返回不是getObject方法返回的值的类型还是未报错。
若有知晓,烦请告知,不胜感激。
这是看完雷丰阳雷老师的ssm课程的笔记,感谢。