- 1 创建对象
- 1.1 通过new方式创建对象
- 1.2 通过注解创建对象
- 1.3 通过XML配置文件创建对象
- 2 注入属性(DI)
- 2.1 通过set方法或者有参构造方法注入属性
- 2.2 通过注解注入属性
- 2.3 通过XML配置文件注入属性
- 3 Bean的作用域
- 4 Bean的生命周期
- 参考资料
- Spring5.x组件图
IOC = XML解析或注解 + 工厂模式 + 反射
- IOC:(Inverse of Control)控制反转。IOC容器实际上就是个Map,存放各种对象。用来实现对象的创建和注入属性。
首相要在项目中倒入Spring相关的jar包,也可以通过maven管理包
准备一个实体类User.java
package com.afuya.pojo;
public class User {
private String name;
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + ''' +
'}';
}
}
1.1 通过new方式创建对象
User user = new User(); System.out.println(user);1.2 通过注解创建对象
准配一个注解的配置类SpringConfig.java,名字随意
package com.afuya.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
//表示当前类作为配置类,替代xml配置文件
@Configuration
@ComponentScan(basePackages = {"com.afuya"}) // 开启组件扫描
public class SpringConfig {
}
实体类加上@Component注解。默认的值为类名的首字母小写,即@Component(value = "user")
- 创建对象的注解有:@Component一般放在pojo层;@Repository一般放在dao层;@Service一般放在service层;@Controller一般放在web层。
package com.afuya.pojo;
import org.springframework.stereotype.Component;
@Component
public class User {
private String name;
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + ''' +
'}';
}
}
通过ApplicationContext对象的getBean方法创建对象
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
// user的值要与实体类中注解的值一样
User user1 = context.getBean("user", User.class);
System.out.println(user1);
1.3 通过XML配置文件创建对象
添加bean1.xml配置文件,直接在src目录下新建即可。
去掉实体类上的注解,通过ApplicationContext对象的getBean方法创建对象
// 注意XML文件的路径
ApplicationContext context1 = new ClassPathXmlApplicationContext("bean1.xml");
User user2 = context1.getBean("user", User.class);
System.out.println(user2);
2 注入属性(DI)
2.1 通过set方法或者有参构造方法注入属性
// 无参构造+set方法注入属性
User user = new User();
user.setName("afuya");
System.out.println(user);
// 有参构造注入属性
User user1 = new User("afu");
System.out.println(user1);
2.2 通过注解注入属性
- @Value注解用于注入普通类型的属性。
- @Autowired和@Qualifier用于注入对象类型。@Autowired根据属性的类型进行注入,@Qualifier根据属性的名称进行注入
package com.afuya.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class User {
@Value(value = "abc")
private String name;
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + ''' +
'}';
}
}
直接获取的对象,里面的属性就已经被注入好了。
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
User user2 = context.getBean("user", User.class);
System.out.println(user2);
// User{name='abc'}
在User.java中添加一个对象类型的属性,准备实体类Dog.java。要有@Component和@Value注解。
package com.afuya.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Dog {
@Value(value = "xiaohei")
private String dogName;
public Dog() {
}
public Dog(String dogName) {
this.dogName = dogName;
}
public String getDogName() {
return dogName;
}
public void setDogName(String dogName) {
this.dogName = dogName;
}
@Override
public String toString() {
return "Dog{" +
"dogName='" + dogName + ''' +
'}';
}
}
在User.java中添加相应的构造方法和set方法
package com.afuya.pojo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class User {
@Value(value = "abc")
private String name;
@Autowired
private Dog dog;
public User() {
}
public User(String name) {
this.name = name;
}
public User(String name, Dog dog) {
this.name = name;
this.dog = dog;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + ''' +
", dog=" + dog +
'}';
}
}
最后在测试方法中获取User对象,里面已经被注入了属性
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
User user2 = context.getBean("user", User.class);
System.out.println(user2);
// User{name='abc', dog=Dog{dogName='xiaohei'}}
2.3 通过XML配置文件注入属性
首先去掉上文中的所有注解。
或者
最后在测试方法中获取User对象,里面已经被注入了属性
ApplicationContext context1 = new ClassPathXmlApplicationContext("bean1.xml");
User user3 = context1.getBean("user", User.class);
System.out.println(user3);
同理,如果其中有对象类型的属性。
或者另一种写法
3 Bean的作用域
- 在XML配置文件的scope属性中可以设置。有五种作用域。
- singleton:Spring默认的作用域。所有的Bean都是单例的。在创建容器时,就同时创建了Bean对象。
- prototye:每次请求都会创建一个新的Bean实例。在创建容器时并没有实例化,而是获取Bean时,才会创建一个对象。
- request:每次HTTP请求都会产生一个新的Bean。仅在当前HTTP Request中有效。
- session:每次HTTP请求都会产生一个新的Bean。仅在当前HTTP Session中有效。
- global-session:全局session中有效。只在portlet应用中才有意义,在Spring5.x中已经移除了portlet。
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
User user = context.getBean("user", User.class);
System.out.println(user); // User{name='abc', dog=Dog{dogName='xiaoghei'}}
User user2 = context.getBean("user", User.class);
System.out.println(user2); // User{name='abc', dog=Dog{dogName='xiaoghei'}}
System.out.println(user == user2); // true
System.out.println(user.equals(user2)); // true
- 可以看到,通过同一个AnnotationConfigApplicationContext对象获取的Bean对象是单例的。
- 可以通过注解和XML配置文件改变作用域
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Scope;
@Component
@Scope(ConfigurableListableBeanFactory.SCOPE_PROTOTYPE)
public class User {
...
}
4 Bean的生命周期
参考资料1.尚硅谷Spring5框架教程(idea版)
2.Spring中bean的作用域与生命周期



