将获取一个对象,从原来的主动new创建,转变成由一个容器进行管理,容器能够自动的创建和配置对象,程序员只需按需索取即可。
XML配置Bean
<!--注册一个Person对象,Spring会自动创建这个Person对象-->
<!--
一个Bean标签可以注册一个组件(类、对象)
class:写要注册的组件的全类名
id:这个对象的唯一表示,以后通过getBean(id)来从容器中找到这个对象,以及ref = id来将这个对象注入到其他组件中
-->
<bean id = "person1" class = "com.atguigu.bean.Person">
<!--使用property标签为Person对象的属性赋值
name:需要赋值的属性名
value:为这个属性赋的值
-->
<property name = "age" value = "18">
</bean>
SpringBean配置
创建一个.xml文件,告诉Spring的IoC容器应该如何创建并组装Bean
<bean id="..." class="..."> </Bean>
class:写要注册的组件的全类名
id:这个对象的唯一表示,以后通过getBean(id)来从容器中找到这个对象,以及ref = id来将这个对象注入到其他组件中
对Bean的成员属性进行赋值
放在<bean> </bean>之间
注入常量值时<property name="成员属性名称" value="注入的值"/>
注入对象实例<property name="对象属性名称" ref="被注入对象的bean的id"/>
LIST属性赋值
<!--为bean进行list类型赋值-->
<property name = "books">
<!--相当于 books = new ArrayList<Book>()-->
<list>
<!-- list标签体中添加每一个元素-->
<!--在内部创建一个bean,相当于为其赋值了一个new Book(),内部bean不可用getBean()获取-->
<bean class="com.atguigu.bean.Book">
<property name = "bookName" value="西游记">
</bean>
<!--也可通过引用外部创建的一个bean-->
<ref = "book1" >
</list>
</property>
Map属性赋值
<!-- Map<String, Object> mas -->
<property name = "maps">
<!-- 相当于 maps = new LinkedHashMap<String, Object>() -->
<map>
<!--一个entry代表一个key-value对 -->
<entry key = "key01" value = "张三"></entry>
<entry key = "key02" value = "18"> </entry>
<!--通过value-ref来引用外部创建的一个bean-->
<entry key = "key03" value-ref = "book01"> </entry>
<entry key = "key04" >
<!--相当于new Car(),set方法初始化,然后赋值给key04的value-->
<bean class = "com.atguigu.bean.Car">
<property name="carName" value="宝马"></property>
</bean>
</entry>
</map>
</property>
value属性即为基本数据类型
util名称空间创建一个可以外部引用的集合
<util:需要创建的集合(map、llst等) id = "外部通过id引用该集合">
在这里放置集合的值
</util:需要创建的集合>
<!--相当于newLinkHashMap<>() -->
<util:map id = "myMap">
<entry key = "key01" value = "张三"></entry>
<entry key = "key02" value = "18"> </entry>
</util:map>
外部通过ref属性来引用
也可以在java代码中使用
Map<String, Object> bean = (Map<String, Object>) ioc.getBean("myMap")
进行属性继承和abstract声明
<bean id = "person1" class = "com.atguigu.bean.Person" abstract = "true">
<property name = "name" value = "张三"></property>
<property name = "age" value = "18"></property>
</bean>
<bean id = "person2" class = "com.atguigu.bean.Person" parent = "person1">
<property name = "name" value = "李四"></property>
</bean>
通过bean标签中的parent属性指定继承的对象,这里的继承只是进行属性的继承(减少相同XML行)实现重用,然后可以用property来为某个属性重新赋值
如果bean标签中的abstract = “true”,则表示该bean只可被属性继承,不运行通过getBean()来获取实例
级联属性赋值
级联属性,即当前当前对象的属性的属性。级联属性赋值,即在引用外部bean进行赋值时,也重新指定该外部bean的某个属性
<bean id = "person3 class = "com.atguigu.bean.Person" abstract = "true">
<property name = "car" ref = "car01"></property>
<property name = "car.price" value = "10000"></property>
</bean>
级联属性可以修改属性的属性,但是注意:原来的bean的值可能会被修改
单实例与多实例Bean
在bean标签的scope属性可以指定bean是创建单实例还是多实例
scope=“prototypr” :多实例的
1.容器启动时默认不会去创建多实例bean
2.getBean获取的时候才会去创建这个bean
3.每次获取都会创建一个新的对象
scope=“singleton” :单实例的,默认的
1.在容器启动完成之前已经创建好对象,保存在容器中(一个大map,通过id获取)
2.任何获取都是获取之前创建好的那个对象
读取.properties文件
.properties文件是key:value的键值对文件
<context:property-placeholder location = "classpath:文件名.properties" />
通过${ key }来动态取出配置文件中某个key对应的值
通常为了区分,将配置文件中的key上加入前缀
例如读取数据库连接
在.properties配置文件中
jdbc.username = root
jdbc.password = 123456
jdbc.jdbcUrl = jdbc:mysql://localhost:3306/test
jdbc.driverClass = com.mysql.jdbc.Driver
在xml配置文件中
<context:property-placeholder location = "classpath.dbconfig.properties" />
<!--这里创建的是一个外部类-->
<bean id="dataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
</bean>
在java代码中即可获取连接池,并获取连接
DataSource bean = ioc.getBean(DataSource.class);
Connection conn = bean.getConnection()
基于XML的自动装配
在bean标签中的属性autowire规定自动装配方式,仅限于对自定义类型的属性有效(类、集合)
<bean id="" class="" autowire="">
autowire=“default/no”:默认,不自动装配,不自动进行属性赋值
按照某种规则自动装配
autowire = “byName”,按照名字:
该bean中有属性private Car car;
1)、以属性名(car)作为id去容器中找到这个组件,给它赋值,如果找不到就赋值null
等价于 car=ioc.getBean(“car”)
autowire=“byType”,按照类型
private Car car
1)、以属性的类型作为查找依据去容器中找到这个组件,如果容器中有多个这个类型的组件,报错
2)、没找到,配置Null
等价于 car=ioc.getBean(Car.class)
autowire=“constructor”,按构造器进行赋值
对于该bean类的有参构造器,先获取该有参构成器的参数列表
1)、先按照参数列表的各参数类型进行装配(成功就赋值),没有就直接赋值为null
2)、如果按照类型找到多个,则按参数的属性名作为id继续匹配,找不到就赋值null
3)、优点是不会报错
EL表达式语言
在spel中,可以使用字面量、引用其他bean、引用其他bean的某个属性值、调用静态方法、调用非静态方法、使用运算符进行运算
使用字面量 value="#{字面量}"
引用其他bean的某个属性值 value="#{bean的id.bean的属性名}"
引用其他bean value="#{bean的id}"
加载IOC配置文件及使用
最后一步,我们需要创建一个Spring的IoC容器实例,然后加载配置文件,让Spring容器为我们创建并装配好配置文件中指定的所有Bean(拿到婚介所的配置清单)
ApplicationContext context = new ClassPathXmlApplicationContext(“application.xml”);
从ApplicationContext中我们可以根据Bean的ID获取Bean,但更多的时候我们根据Bean的类型获取Bean的引用
UserService user=context.getBean(UserService.class);
Person person = (Person)context.getBean(“person1”)
Person person = context.getBean( “person2”, Person.class)
//按类型查找的优势是不必进行类型转换,但是当创建了多个Person类的对象时,就不能成功找到,只能按照id查找
几个细节
1.ApplicationContext接口的两个实现类
ClassPathXmlApplicationContext()
FileSystemXmlApplicationContext()
区别在于,前者传入的是classpath:的相对路径,即ioc容器的配置文件在类路径下
后者可以使用绝对路径,配置文件可以在磁盘路径下
2.ioc容器中的对象会在容器创建时就已经创建好
3.同一个组件在ioc容器中是单实例的,即多次getBean获得的是同一个对象
4.IOC容器在创建这个组件对象的时候,(property)会利用setter方法为javaBean的属性进行赋值
5.javaBean的属性名是由什么绝对的?getter/setter方法是属性名;set后面那一串首字母小写就是属性名
private String lastName?
所有getter/setter都自动生成