spring源码学习(一)spring复习之IOC
Spring的核心思想

IOC
1、BeanFactory
示例
public static void main(String[] args) {
//bean工厂
DefaultListableBeanFactory beanFactory =new DefaultListableBeanFactory();
//xml读取
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
//读取xml
reader.loadBeanDefinitions("beans.xml");
UserService userService =(UserService) beanFactory.getBean("userService");
System.out.println(userService);
}
xml文件
<?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 id="userService" class="com.cdc.service.UserServiceImpl">
</bean>
</beans>
1.1、set注入
xml文件
<bean id="userService" class="com.cdc.service.impl.UserServiceImpl">
<property name="abcDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="com.cdc.dao.impl.UserDaoImpl">
</bean>
UserDaoImpl.java
public class UserDaoImpl implements UserDao {
}
UserServiceImpl.java
public class UserServiceImpl implements UserService {
public void setAbcDao(UserDao userDao){
System.out.println("set注入啦:"+userDao);
}
}
测试文件
public class TestSpringIOC {
public static void main(String[] args) {
//bean工厂
DefaultListableBeanFactory beanFactory =new DefaultListableBeanFactory();
//xml读取
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
//读取xml
reader.loadBeanDefinitions("beans.xml");
UserService userService =(UserService) beanFactory.getBean("userService");
System.out.println(userService);
}
}
输出:
set注入啦:com.cdc.dao.impl.UserDaoImpl@56de5251
com.cdc.service.impl.UserServiceImpl@419c5f1a
- 注意set方法注入关键,set方法名,后面第一个字母转小写,要跟<property name="abcDao" ,里面的name对应好
2、ApplicationContext (一)
<bean id="userService" class="com.cdc.service.impl.UserServiceImpl">
<property name="abcDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="com.cdc.dao.impl.UserDaoImpl">
</bean>
public class TestApplicationContext {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService =(UserService) applicationContext.getBean("userService");
System.out.println(userService);
}
}
通配符方式加载多个配置文件

3、ApplicationContext与BeanFactory关系


- ApplicationContext内部有个BeanFactory接口的实现类DefaultListableBeanFactory

- DefaultListableBeanFactory内部有个beanDefinitionMap,是bean的定义信息集合,现在有2个bean

- DefaultListableBeanFactory内部有个singletonObjects,是单例池,里面放的是具体的bean
spring web的ApplicationContext
后面再翻看

4、ApplicationContext (二)
4.1、别名
<bean class="com.cdc.service.impl.UserServiceImpl">
<property name="abcDao" ref="userDao"></property>
</bean>


- 之前配置的id即bean的别名,getBean("userService"),就是通过别名获取的。
- 没有配id,默认别名就是类的全限定名,通过这样的方式获取bean,
UserService userService =(UserService) applicationContext.getBean("com.cdc.service.impl.UserServiceImpl");
4.1.1取多个别名
<bean id="userService" name="aaa,ccc,bbb" class="com.cdc.service.impl.UserServiceImpl">
<property name="abcDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="com.cdc.dao.impl.UserDaoImpl">
</bean>
public class TestApplicationContext {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService =(UserService) applicationContext.getBean("userService");
UserService userService2 =(UserService) applicationContext.getBean("aaa");
UserService userService3 =(UserService) applicationContext.getBean("bbb");
UserService userService4 =(UserService) applicationContext.getBean("ccc");
System.out.println(userService);
System.out.println(userService2);
System.out.println(userService3);
System.out.println(userService4);
}
}
默认别名是id


BeanFactory内部有个aliasMap,可以进行别名的映射

4.1.2 没有配置id时,默认别名取第一个 aaa
<bean name="aaa,ccc,bbb" class="com.cdc.service.impl.UserServiceImpl">
<property name="abcDao" ref="userDao"></property>
</bean>
4.2 scope 作用范围
4.2.1默认单例
<bean id="userService" class="com.cdc.service.impl.UserServiceImpl">
</bean>
4.2.2可原型模式
<bean id="userService" class="com.cdc.service.impl.UserServiceImpl" scope="prototype">
</bean>
public class TestApplicationContext {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService =(UserService) applicationContext.getBean("userService");
UserService userService2 =(UserService) applicationContext.getBean("userService");
UserService userService3 =(UserService) applicationContext.getBean("userService");
System.out.println(userService);
System.out.println(userService2);
System.out.println(userService3);
}
}
输出:
com.cdc.service.impl.UserServiceImpl@43195e57
com.cdc.service.impl.UserServiceImpl@333291e3
com.cdc.service.impl.UserServiceImpl@479d31f3
4.3延迟加载
<bean id="userService" class="com.cdc.service.impl.UserServiceImpl" lazy-init="true">
</bean>
创建容器后,单例池singletonObjects没有bean,执行了getBean方法时,才创建bean放进单例池。
//1.创建容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.从容器中取bean
UserService userService =(UserService) applicationContext.getBean("userService");
System.out.println(userService);
- 注意,创建容器后,beanDefinitionMap是有userService的bean定义信息的
4.4 读取多个xml配置文件,以及根据类型获取bean

4.5 spring是默认调用bean的无参构造方法实例化的
public class UserServiceImpl implements UserService {
public UserServiceImpl(){
System.out.println("实例化,调用无参构造");
}
private UserDao userDao;
//set注入,set后面的字符串
public void setAbcDao(UserDao userDao){
this.userDao=userDao;
System.out.println("set注入啦:"+userDao);
}
}
public class TestApplicationContext {
public static void main(String[] args) {
//1.创建容器,可以根据多个配置文件创建
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.从容器中取bean
UserService userService =(UserService) applicationContext.getBean("userService");
System.out.println(userService);
}
}
输出:
实例化,调用无参构造
com.cdc.service.impl.UserServiceImpl@123ef382
4.6构造注入
public class UserServiceImpl implements UserService {
public UserServiceImpl(){
System.out.println("实例化,调用无参构造");
}
public UserServiceImpl(String name,int num){
System.out.println("实例化,调用有参构造"+name+num);
}
private UserDao userDao;
//set注入,set后面的字符串
public void setAbcDao(UserDao userDao){
this.userDao=userDao;
System.out.println("set注入啦:"+userDao);
}
}
<bean id="userService" class="com.cdc.service.impl.UserServiceImpl">
<constructor-arg name="name" value="nihao"></constructor-arg>
<constructor-arg name="num" value="60"></constructor-arg>
<property name="AbcDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="com.cdc.dao.impl.UserDaoImpl">
</bean>
输出:
实例化,调用有参构造nihao60
set注入啦:com.cdc.dao.impl.UserDaoImpl@22555ebf
com.cdc.service.impl.UserServiceImpl@4d1c00d0
4.7 静态方法工厂加载Bean
public class BookFactory {
public static BookDTO bookDTOBuild(String carName,int num){
//使用静态方法注入
//可以在此处写点别的代码
return new BookDTO();
}
}
springBook.xml
<bean id="book" class="com.cdc.factory.BookFactory" factory-method="bookDTOBuild">
<!--构造参数注入-->
<constructor-arg name="carName" value="benz"></constructor-arg>
<constructor-arg name="num" value="60"></constructor-arg>
</bean>
public class TestApplicationContextFactory {
public static void main(String[] args) {
//1.创建容器,可以根据多个配置文件创建
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("springBook.xml");
//2.从容器中取bean
BookDTO bookDTO =(BookDTO) applicationContext.getBean("book");
System.out.println(bookDTO);
}
}
4.8 实例方法工厂加载Bean
public class MyBeanFactory2 {
public UserDao userDao(String carName,int num){
return new UserDaoImpl();
}
}
<bean id="myBeanFactory2" class="com.cdc.factory.MyBeanFactory2"></bean>
<bean id="userDao2" factory-bean="myBeanFactory2" factory-method="userDao">
<!--构造参数注入-->
<constructor-arg name="carName" value="benz"></constructor-arg>
<constructor-arg name="num" value="60"></constructor-arg>
</bean>
UserDao userDao2 =(UserDao) applicationContext.getBean("userDao2");
System.out.println(userDao2);
- 配置实例化工厂类,实例化工厂类来产生bean
与静态方法工厂的区别
实例化工厂类也要进单例池

4.9FactoryBean实现延迟加载
public class MyBeanFactory3 implements FactoryBean<UserDao> {
@Override
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
@Override
public Class<?> getObjectType() {
return UserDao.class;
}
}
<bean id="userDao3" class="com.cdc.factory.MyBeanFactory3"></bean>
4.9.1 执行了ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");单例内不会有userDao3的实例,只会有一个实现FactoryBean接口的实例

4.9.2 执行了UserDao userDao3 =(UserDao) applicationContext.getBean("userDao3");才会在缓冲池内有个userDao3的实例,下次getBean,也是从该缓冲池取

4.10属性注入集合、数据
4.10.1List<String>集合


4.10.2.1对象集合,集合内代表三个不同的UserDaoImpl实例


4.10.2.2对象集合,也可配置在外面

set String集合


set 对象集合


map 集合


properties对象


4.11 自动注入

1.通过名字自动注入
public class UserServiceImpl implements UserService {
public void setUserDao3(UserDao userDao){
System.out.println("set注入userDao:"+userDao);
}
}
<beans>
<bean id="UserService" class="com.cdc.service.impl.UserServiceImpl" autowire="byName"></bean>
<bean id="userDao3" class="com.cdc.dao.impl.UserDaoImpl"></bean>
</beans>
- set方法后面的名字一定要和bean的id(name)一致
2.通过类型自动注入
<beans>
<bean id="UserService" class="com.cdc.service.impl.UserServiceImpl" autowire="byType"></bean>
<bean id="userDao3" class="com.cdc.dao.impl.UserDaoImpl"></bean>
</beans>
4.12 命名空间
4.12.1 spring默认的命名空间

4.12.2 引入其他的命名空间

4.12.2.1 接着就可以使用其他的标签了

4.12.3
4.12.3.1

4.12.3.2

4.12.3.3

4.12.4
4.12.4.1

4.12.4.2

4.12.4.3

4.13 profile环境标签

指定test,可以获取userDao1


不指定环境,只能获取到userService和userDao

- 指定dev,可以获取userService1、userService和userDao
- 指定test,可以获取userDao1、userService和userDao
- 上图红色框框的相当于公共部分
4.13 import标签

4.13.1 示例
applicationContext.xml文件



只读取applicationContext.xml文件,就可以读取到applicationContext-order.xml和applicationContext-user.xml配置的bean

4.14 alias别名标签


浙公网安备 33010602011771号