对昨天的总结:
review ioc
spring整合性的框架、基础性的框架
ioc:控制反转
控制:实例的生成权
反转:实例的生成权由应用程序反转给ioc容器
di:依赖注入
应用程序(贫穷)和ioc容器(富有)
依赖:谁依赖谁?为什么?
注入:谁注入谁?注入了什么?
入门案例
导包spring-context(5+1) junit
引入spring配置文件:application.xml → 约束schema:
1、已有项目
2、官网的参考文档appendix schema
3、创建文件模板 file templates
使用:
单元测试类中写单元测试的方法
ApplicationContext对象 → ClasspathXMLApplicationContext(加载classpath下的配置文件)
ApplicationContext的getBean方法
getBean → String(根据id取出) → class(根据类型取出 → 这个类型的组件在容器中只有一个) → String,Class(根据id和类型取出)
两个入门案例
HelloService →
HelloService helloDao
维护组件之间的依赖关系 helloService依赖helloDao
<bean id=”helloService” class=”全类名”>
<property name=”set方法对应” ref=”helloDao”/>
<-- 如果不想使用ref属性,可以使用ref或bean子标签 -->
<ref bean=”组件id”/>是property的子标签
<bean class=”dao全类名”/>局部组件
bean>
<bean id=”helloDao” class=”全类名”/>
api
FileSystemXmlApplicationContenxt 文件系统
ClassPathXmlApplicationContenxt classpath
BeanFactory
BeanFactory和FactoryBean的区别
xml组件的注册
构造方法
有参
组件中包含有参构造方法
5.1.2无参(最常用)
并不常用,通常用于整合已有的代码
5.2.1静态工厂
工厂中生产方法是静态的
5.2.2实例工厂
先去注册工厂实例
生命周期
实例化
设置参数 set方法
Aware → BeanNameAware、BeanFactoryAware、ApplicationContextAware
BeanPostProcessor的before(容器中有组件实现这个接口,而不是当前)
InitializingBean的afterPropertiesSet
自定义的init方法 → bean标签中配置init-method
BeanPostProcessor的after
组件就可以使用了
容器关闭
DisposableBean 的destroy
自定的destroy方法 → bean标签中配置destroy-method
第一步是实例化 → 在构造方法中打印一些东西 → 通过这种方式可以看组件是否注册
动态代理增强写在BeanPostProcessor中。会指定容器中所有的组件,如果想要对指定的组件进行动态代理增强,可以写if判断
jdk动态代理(组件要有接口的实现,从容器中获得这个组件要用接口来接收)
建议使用cglib动态代理
能否保证容器中所有的组件都有接口的实现???
Scope
在maven的dependency中见过这个词 → 依赖的作用域 test provided runtime compile
而今天讲的Scope是指组件的作用域:singleton(单例)、prototype(原型)
singleton:容器中的组件 始终以单例的形式存在 → 默认是单例
prototype:每次从容器中取出组件都是一个新的组件 → 相当于每一次new一个新的
scope和生命周期的关系
singleton:容器初始化的时候,开始生命周期
prototype:当你去获得这个组件的时候,才开始生命周期,生命周期没有destroy。
xml的spring配置文件中如何配置CollectionBean
User:
package com.cskaoyan.bean;
import lombok.Data;
@Data
public class User {
String username;
String password;
}
CollectionBean :
package com.cskaoyan.bean;
import lombok.Data;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
@Data
public class CollectionBean {
Object[] arrayParam;
//String[] stringArray;
//User[] users;
List listParam;
Set setParam;
Map mapParam;
Properties properties;
}
application.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="user" class="com.cskaoyan.bean.User">
<property name="username" value="songge"/>
<property name="password" value="niupi"/>
bean>
<bean class="com.cskaoyan.bean.CollectionBean">
<property name="arrayParam">
<array>
<value>arraydata1value>
<value>234value>
<ref bean="user"/>
<bean class="com.cskaoyan.bean.User">
<property name="username" value="ligenli"/>
<property name="password" value="daqi"/>
bean>
array>
property>
<property name="listParam">
<list>
<value>arraydata1value>
<value>234value>
<ref bean="user"/>
<bean class="com.cskaoyan.bean.User">
<property name="username" value="ligenli"/>
<property name="password" value="daqi"/>
bean>
list>
property>
<property name="setParam">
<set>
<value>arraydata1value>
<value>234value>
<ref bean="user"/>
<bean class="com.cskaoyan.bean.User">
<property name="username" value="ligenli"/>
<property name="password" value="daqi"/>
bean>
set>
property>
<property name="mapParam">
<map>
<entry key="key1" value="value1"/>
<entry key-ref="user" value-ref="user"/>
<entry key="key2">
<value>value2value>
entry>
<entry key="user2">
<ref bean="user"/>
entry>
<entry key="user3">
<bean class="com.cskaoyan.bean.User">
<property name="username" value="ligenli"/>
<property name="password" value="daqi"/>
bean>
entry>
map>
property>
<property name="properties">
<props>
<prop key="key1">value1prop>
<prop key="key2">234prop>
props>
property>
bean>
beans>
测试类:
package com.cskaoyan;
import com.cskaoyan.bean.CollectionBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class CollectionBeanTest {
@Test
public void mytest(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
CollectionBean bean = applicationContext.getBean(CollectionBean.class);
System.out.println(bean);
}
}
array、list、set只有property的子标签不同,其余的写法都是相同的。即array使用的是array标签,list使用的是list标签,set使用的是set标签。
map和properties为什么没有和上述几个Collection一起使用呢?
map需要key和value:key和value可以是字符串、基本类型、包装类、javabean
properties也需要key和value: key和value不能是javabean
测试类的运行结果:
注解(非常重要非常常用的内容)
使用注解后组件id是什么:
可以指定id:@Component(“helloService”)使用注解的value属性指定id
可以使用默认id:如果没有指定id,那么使用的是默认id
a. 字符串、基本类型、包装类(@Value)
第一种是将@value中的值写死。
第二种是引用properties配置文件中的key
分两步:
1、在spring配置文件中引入properties文件
2、在@value注解中引用properties文件中的key
b. javabean
1、@Autowired → getBean(class) → 容器中这个类型的组件只有一个
如果容器中的组件不止一个,其实使用@Autowired也可以取出来,但是对成员变量是有要求的,把组件id写成成员变量名。(这种方式不常用)
2、@Autowired+@Qualifier → 容器中这个类型的组件不止一个,通过@Qualifier指定组件id
3、@Resource → 默认可以按照类型去取(当容器中这个类型的组件只有一个的时候),也可以使用name属性指定组件id
类型就是和class相关的,class是什么,类型就是什么
类型组件只有一个
类型组件不止一个
两个组件的类型都是UserDao。
或者
这种方法很少使用。
init-method(自定义的init方法)
destroy-method(自定义的destroy方法)
之前是写在bean标签中的属性
之前单元测试都是先去获得ApplicationContext对象
spring对单元测试有良好的支持
可以在单元测试类中直接使用3.2注入类的注解从容器中取出组件
加载配置文件
在配置类上增加注解
@Runwith 中要写一个类加载器
@ContextConfiguration 加载配置文件
不是说所有的类都要到spring容器中注册:一般是提供了某些方法的类要注册到容器中,或者提供了某些功能的类要注册到容器中。比如某些service或dao
new User();和new Product();不需要注册到容器中。