Spring入门程序解析
本篇博客演示一个简单的spring小程序的实现
-
创建实体类User和Master
public class User { private String userName; public User() { System.out.println("User无参构造方法被调用了..."); } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public void show() { System.out.println("userName="+userName); } }
public class Master { private int masterAge; public Master() { System.out.println("master的无参构造方法被调用了..."); } public int getMasterAge() { return masterAge; } public void setMasterAge(int masterAge) { this.masterAge = masterAge; } public void show() { System.out.println("masterAge="+masterAge); } }
这里我覆盖了两个实体类的无参构造方法,方便我们观察spring容器对类的加载
-
创建applicationContext.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="master" class="com.fs.pojo.Master"> <property name="masterAge" value="21"/> </bean> <bean id="user" class="com.fs.pojo.User"> <property name="userName" value="kiddo"/> </bean> </beans>
这里简单讲一下bean代表的意思
bean其实就可以看成是我们写的一个类,id属性的值可以看成我们我们new的对象名,class是这个类的全限定类名
< property >就是属性的意思,在Master类中我们就有个masterAge属性,这里的value使我们自定义的,我们给它赋值21
下面user这个bean同理
3. 创建测试类
```java
public class MyTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Master master = (Master)applicationContext.getBean("master");
master.show();
// User user = applicationContext.getBean("user",User.class);
// user.show();
}
}
```
这里我们通过加载spring容器来获取我们想要的对象:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
通过getBean(“id”)方法取到对象,id就是applicationContext.xml里bean标签的id,这里我们获得的对象是一个Object类型,所以我们需要强转成Master类,又或者通过第7行代码这种方法就不用强转了。
接着调用show方法,运行结果如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201011234950270.png#pic_center)
可以看到,**虽然我们只获取了Master对象,但是User类却也被实例化了,这是因为当我们加载applicationContext.xml文件时,里面所有的bean都会被按顺序实例化**,有多少个bean就new了多少个对象,以后当我们需要用到对象的时候直接通过getBean()方法去取就行了,是不是很方便呢?这就体现了IOC的思想了,想要什么对象由我们自己决定去取,而不用一个一个去new ;通过打印结果我们也看出,我们在配置文件中给masterAge传的值21也成功注入了,这是DI的一种方法——通过setter方法注入。
然后我们注释Master的代码,执行一下User的方法
```java
public class MyTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// Master master = (Master)applicationContext.getBean("master");
// master.show();
User user = applicationContext.getBean("user",User.class);
user.show();
}
}
```
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201011234833154.png#pic_center)
看,首先还是先由配置文件实例化所有的bean,然后我们给属性userName传入的value也成功注入了。
不过并不是每次getBean都会重新new一个对象,而是只有一个对象,这就是bean的默认作用域”singleton“——单例模式,不过可以通过把bean标签的scope属性设置成” prototype“做到每次getBean都实例化一个对象,不过一般情况下不提倡这么做
public class MyTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// Master master = (Master)applicationContext.getBean("master");
// master.show();
User user = applicationContext.getBean("user",User.class);
// user.show();
User user1 = applicationContext.getBean("user",User.class);
// user.show();
System.out.println(user==user1);
}
}
虽然我们获取了两次User对象,但由于bean默认是单例的,所以从运行结果为true我们可以看到user和user1确实是同一个对象。
重要知识点
- @Component、@Service、@Bean 等注解在 AbstractApplicationContext的 refresh方法中的 invokeBeanFactoryPostProcessors(beanFactory) 方法中被ConfigurationClassPostProcessor解析,即被这些注解标注的类的bean定义在此时都被添加进beanFactory里了;
- ConfigurationClassPostProcessor 是第一个被执行的 BeanDefinitionRegistryPostProcessor(实现了 @PriorityOrdered 接口),该bean工厂处理器的作用其实就是通过解析诸如 @Bean、@Component、@Import 等注解来为bean工厂添加一些bean定义。