Spring学习-IOC容器
通过XML管理Bean对象
无参构造器
// 接口
public interface Service{
void doService();
}
// 实现类
public class ServiceImpl implements Service{
void doService()
{
System.out.println("来自ServiceImpl");
}
}
XML文件配置:
<bean id="serviceImpl" class="com.example.demo.ServiceImpl"/>
调用:
// 通过xml文件获取上下文
ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
// 从ioc容器中获取bean对象
Service bean = context.getBean("serviceImpl");
// 调用对应的方法
bean.doService();
有参构造器
public class ServiceImplWithArgs implements Service{
String name;
int value;
ServiceImplWithArgs(String name, int value){
this.name = name;
this.value = value;
}
void doService(){
System.out.println("来自ServiceImplWithArgs");
}
}
XML文件:
<!--方式一:通过指定变量名进行注入-->
<bean id="serviceImplWithArgs" class="com.example.demo.ServiceImplWithArgs">
<constructor-arg name="name" value="名字"/>
<constructor-arg name="value" value="10"/>
</bean>
<!--方式二:通过索引进行注入-->
<bean id="serviceImplWithArgs" class="com.example.demo.ServiceImplWithArgs">
<constructor-arg index="0" value="名字"/>
<constructor-arg index="1" value="10"/>
</bean>
属性注入
java代码:
public class MyBean{
private String var1;
private int val2;
private String[] array;
private List<String> list;
private Set<String> set;
private Map<String, Integer> map;
private Properties properties;
private String var3;
// 省略对应的setter和getter方法
}
XML文件
<bean id = "mybean" class="com.example.demo.MyBean">
<!--注入String类型变量-->
<property name="var1" value="test"/>
<!--注入int类型变量-->
<property name="val2" value="1"/>
<!--注入数组类型变量-->
<property name="array">
<array>
<value>array1</value>
<value>array2</value>
</array>
</property>
<!--list注入-->
<property name="list">
<list>
<value>list1</value>
<value>list2</value>
</list>
</property>
<!--map注入-->
<property name="map">
<map>
<entry key="key1" value="1"/>
<entry key="key2" value="2"/>
<entry key="key3" value="3"/>
</map>
</property>
<!--properties注入-->
<property name="properties">
<props>
<prop key="name">myName</prop>
<prop key="age">10</prop>
</props>
</property>
<!--null注入-->
<property name="var3">
<null/>
</property>
</bean>
bean生命周期
Spring中默认为单例模式创建bean对象,所以存在线程安全问题。
解决:
- 将bean设置为原型模式
prototype
。 - 将有线程安全问题的字段设为ThreadLocal变量
XML文件
<!--原型模式,每次获取bean时为不同的对象-->
<bean id="local" class="com.example.demo.MyBean" scope="prototype"/>
<!--单例模式,每次获取bean为相同的对象-->
<bean id="mybean" class="com.example.demo.MyBean" scope="singleton"/>
bean的自动装配
- 通过name进行自动装配
- 通过type进行自动装配
XML文件
<!--根据变量名进行自动装配-->
<bean id="bean" class="com.example.demo.MyBean" autowire="byName"/>
<!--根据变量类型进行自动装配-->
<bean id="bean" class="com.example.demo.MyBean" autowire="byType"/>
Spring自动装配Autowired
基于XML文件的自动装配
XML文件:"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"
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">
<!--注解开启-->
<context:annotation-config/>
<!--扫描指定路径下的组件,托管bean,完成自动装配-->
<context:component-scan base-package="com.example.demo"/>
</beans>
java文件
@Component
public class Node{
@Value("default value")
private String value;
}
@Component
@Data
public class Tree{
@Autowired
private Node node;
}
// 测试类
public class MyTest{
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext.xml");
Tree tree = context.getBean(Tree.class);
System.out.println(tree.getNode().value);
}
}
注:通过XML完成自动装配的注意事项:
- 在xml文件中开启注解
<context:annotation-config/>
- 在xml文件中开启自动装配指定路径的所有组件
<context:component-scan base-package="com.example.demo"/>
- 在组件类中加上注解@Component
- 在需要自动装配的字段上使用注解@Autowired完成自动装配
类似于@Component的注解:都是将指定的类注册到Spring容器中
- Dao层:@Repository
- Service层:@Service
- Controller层:@Controller
自动装配的注解
- @Autowired:用于类中需要自动装配的字段
- @Resource:通过名字和类型进行自动装配
- @Nullable:用在参数列表中,表示该参数可为null
作用域:加在类名上
@Scope("singleton"):指定为单例
@Scope("prototype"):指定为原型
基于JavaConfig类完成自动装配
配置类
@Component // 配置类需要注册为组件
@ComponentScan("com.example.demo") // 扫描指定路径下的组件
public class MyConfig{
}
需要Spring托管的类
@Component
@Data
public class Node{
@Value("default value")
private String value;
}
需要自动装配的类
@Component
public class Tree{
@Autowired // 实现自动装配
private Node node;
public void print()
{
System.out.println(node.getValue());
}
}
测试类
public class MyTest{
@Test
public void test()
{
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); // 加载配置类
Tree tree = context.getBean(Tree.class); // 通过指定类的class获取bean对象
// Tree tree = (Tree)context.getBean("tree"); // 通过类名也可以获取对应的bean对象
tree.print();
}
}