第一个Spring程序详细剖析
本篇文章说说Spring的第一个程序详细的剖析,上篇说了spring第一个程序的前期准备工作
https://blog.51cto.com/u_15485663/6110947
配合视频教程观看,更易理解吸收,动力节点老杜的Spring6教程采用难度逐步递进的方式,从入门的第一个程序到手写Spring框架,真正的能够让小白成为老手。如果你是老程序员不妨看看手写Spring框架,也会让你受益颇多。
<bean id="userBean" class="com.powernode.spring6.bean.User"/>
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Object userBean = applicationContext.getBean("userBean");
1. bean标签的id属性可以重复吗?
package com.powernode.spring6.bean;
/**
* @author 动力节点
* @version 1.0
* @className Vip
* @since 1.0
**/
public class Vip {
}
<?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="userBean" class="com.powernode.spring6.bean.User"/>
<bean id="userBean" class="com.powernode.spring6.bean.Vip"/>
</beans>
运行测试程序:
通过测试得出:在spring的配置文件中id是不能重名。
2. 底层是怎么创建对象的,是通过反射机制调用无参数构造方法吗?
package com.powernode.spring6.bean;
/**
* bean,封装用户信息。
* @author 动力节点
* @version 1.0
* @since 1.0
*/
public class User {
public User() {
System.out.println("User的无参数构造方法执行");
}
}
在User类中添加无参数构造方法,如上。
运行测试程序:
通过测试得知:创建对象时确实调用了无参数构造方法。
如果提供一个有参数构造方法,不提供无参数构造方法会怎样呢?
package com.powernode.spring6.bean;
/**
* bean,封装用户信息。
* @author 动力节点
* @version 1.0
* @since 1.0
*/
public class User {
/*public User() {
System.out.println("User的无参数构造方法执行");
}*/
public User(String name){
System.out.println("User的有参数构造方法执行");
}
}
运行测试程序:
通过测试得知:spring是通过调用类的无参数构造方法来创建对象的,所以要想让spring给你创建对象,必须保证无参数构造方法是存在的。
Spring是如何创建对象的呢?原理是什么?
// dom4j解析beans.xml文件,从中获取class的全限定类名
// 通过反射机制调用无参数构造方法创建对象
Class clazz = Class.forName("com.powernode.spring6.bean.User");
Object obj = clazz.newInstance();
3. 把创建好的对象存储到一个什么样的数据结构当中了呢?
4. spring配置文件的名字必须叫做beans.xml吗?
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
通过以上的java代码可以看出,这个spring配置文件名字是我们负责提供的,显然spring配置文件的名字是随意的。
5. 像这样的beans.xml文件可以有多个吗?
再创建一个spring配置文件,起名:spring.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="vipBean" class="com.powernode.spring6.bean.Vip"/>
</beans>
package com.powernode.spring6.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Spring6Test {
@Test
public void testFirst(){
// 初始化Spring容器上下文(解析beans.xml文件,创建所有的bean对象)
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml","spring.xml");
// 根据id获取bean对象
Object userBean = applicationContext.getBean("userBean");
Object vipBean = applicationContext.getBean("vipBean");
System.out.println(userBean);
System.out.println(vipBean);
}
}
运行测试程序:
通过测试得知,spring的配置文件可以有多个,在ClassPathXmlApplicationContext构造方法的参数上传递文件路径即可。这是为什么呢?通过源码可以看到:
6. 在配置文件中配置的类必须是自定义的吗,可以使用JDK中的类吗,例如:java.util.Date?
<?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="userBean" class="com.powernode.spring6.bean.User"/>
<!--<bean id="userBean" class="com.powernode.spring6.bean.Vip"/>-->
<bean id="dateBean" class="java.util.Date"/>
</beans>
package com.powernode.spring6.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Spring6Test {
@Test
public void testFirst(){
// 初始化Spring容器上下文(解析beans.xml文件,创建所有的bean对象)
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml","spring.xml");
// 根据id获取bean对象
Object userBean = applicationContext.getBean("userBean");
Object vipBean = applicationContext.getBean("vipBean");
Object dateBean = applicationContext.getBean("dateBean");
System.out.println(userBean);
System.out.println(vipBean);
System.out.println(dateBean);
}
}
运行测试程序:
通过测试得知,在spring配置文件中配置的bean可以任意类,只要这个类不是抽象的,并且提供了无参数构造方法。
7. getBean()方法调用时,如果指定的id不存在会怎样?
运行测试程序:
通过测试得知,当id不存在的时候,会出现异常。
8. getBean()方法返回的类型是Object,如果访问子类的特有属性和方法时,还需要向下转型,有其它办法可以解决这个问题吗?
User user = applicationContext.getBean("userBean", User.class);
9. ClassPathXmlApplicationContext是从类路径中加载配置文件,如果没有在类路径当中,又应该如何加载配置文件呢?
<?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="vipBean2" class="com.powernode.spring6.bean.Vip"/>
</beans>
ApplicationContext applicationContext2 = new FileSystemXmlApplicationContext("d:/spring6.xml");
Vip vip = applicationContext2.getBean("vipBean2", Vip.class);
System.out.println(vip);
没有在类路径中的话,需要使用FileSystemXmlApplicationContext类进行加载配置文件。
这种方式较少用。一般都是将配置文件放到类路径当中,这样可移植性更强。
10. ApplicationContext的超级父接口BeanFactory。
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring.xml");
Object vipBean = beanFactory.getBean("vipBean");
System.out.println(vipBean);
BeanFactory是Spring容器的超级接口。ApplicationContext是BeanFactory的子接口。