Spring IoC 容器概述
IoC 容器示例
/**
* ApplicationContext 作为 IoC 容器示例
*/
public class AnnotationApplicationContextAsIoCContainerDemo {
public static void main(String...args){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AnnotationApplicationContextAsIoCContainerDemo.class);
applicationContext.refresh();
User user = applicationContext.getBean("user", User.class);
System.out.println(user);
applicationContext.close();
}
@Bean
public User user(){
User user = new User();
user.setName("fly");
user.setAge(12);
return user;
}
}
/**
* BeanFactory 作为 IoC 容器示例
*/
public class BeanFactoryAsIoCContainerDemo {
public static void main(String...args){
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
String location = "classpath:/META-INF/dependency-lookup-context.xml";
reader.loadBeanDefinitions(location);
Person person = beanFactory.getBean("person", Person.class);
System.out.println(person);
//Person(id=1, name=fly, city=HANGZHOU, workCities=[BEIJING, HANGZHOU], lifeCities=[BEIJING, SHANGHAI],
// company=Company(name=beijing), context={p2=2, p1=1}, contextAsText=null)
}
}
META-INF/dependency-lookup-context.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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<bean id="person" class="com.fly.demo.Person">
<property name="id" value="1"/>
<property name="name" value="fly"/>
<property name="city" value="HANGZHOU"/>
<property name="workCities" value="BEIJING,HANGZHOU"/>
<property name="lifeCities">
<list>
<value>BEIJING</value>
<value>SHANGHAI</value>
</list>
</property>
<property name="context">
<props>
<prop key="p1">1</prop>
<prop key="p2">2</prop>
</props>
</property>
<property name="company" ref="company"/>
</bean>
<bean id="company" class="com.fly.demo.Company">
<property name="name" value="beijing"/>
</bean>
</beans>
User
@Data
public class User {
private String name;
private Integer age;
}
Person
import lombok.Data;
import java.util.List;
import java.util.Properties;
@Data
public class Person {
private Long id;
private String name;
private City city;
private City[] workCities;
private List<City> lifeCities;
private Company company;
private Properties context;
private String contextAsText;
}
City
public enum City {
BEIJING,
HANGZHOU,
SHANGHAI
}
Company
@Data
public class Company {
private String name;
}
Spring IoC 依赖查找
dependency-lookup-context.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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<bean id="person" class="com.fly.demo.Person">
<property name="id" value="1"/>
<property name="name" value="fly"/>
<property name="city" value="HANGZHOU"/>
<property name="workCities" value="BEIJING,HANGZHOU"/>
<property name="lifeCities">
<list>
<value>BEIJING</value>
<value>SHANGHAI</value>
</list>
</property>
<property name="context">
<props>
<prop key="p1">1</prop>
<prop key="p2">2</prop>
</props>
</property>
<property name="company" ref="company"/>
</bean>
<bean id="company" class="com.fly.demo.Company">
<property name="name" value="beijing"/>
</bean>
<bean id="user" class="com.fly.demo.User">
<property name="name" value="fly"/>
<property name="age" value="14"/>
</bean>
<!-- 普通 beanDefinition GenericBeanDefinition -->
<!-- 合并后 GenericBeanDefinition 变成 RootBeanDefinition,并且覆盖 parent 相关配置-->
<!-- primary = true , 增加了一个 action 属性 -->
<bean id="superUser" class="com.fly.demo.SuperUser" parent="user" primary="true">
<property name="action" value="sky"/>
</bean>
<bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
<property name="targetBeanName" value="user"/>
</bean>
</beans>
Super
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Super {
}
import com.fly.demo.Super;
import com.fly.demo.User;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Map;
/**
* 依赖查找示例
*/
public class DependencyLookupDemo {
public static void main(String...args){
String location = "classpath:/META-INF/dependency-lookup-context.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(location);
// 按照类型查找
lookupByType(applicationContext);
// 按照类型查找结合对象
lookupCollectionByType(applicationContext);
// 通过注解查找对象
lookupByAnnotationType(applicationContext);
// Bean 延迟依赖查找接口 ObjectFactory<T>
lookupInLazy(applicationContext);
}
private static void lookupInLazy(ApplicationContext applicationContext) {
ObjectFactory<User> objectFactory = (ObjectFactory<User>) applicationContext.getBean("objectFactory");
System.out.println("延迟查找:" + objectFactory.getObject());
}
private static void lookupByAnnotationType(ApplicationContext applicationContext) {
Map<String, Object> objectMap = applicationContext.getBeansWithAnnotation(Super.class);
System.out.println("查找标注 @Super 所有的集合对象:" + objectMap);
}
private static void lookupCollectionByType(ApplicationContext applicationContext) {
Map<String, User> userMap = applicationContext.getBeansOfType(User.class);
System.out.println("查找到的所有的 User 集合对象:" + userMap);
}
private static void lookupByType(ApplicationContext applicationContext) {
// 根据类型,所以不能有重复的,或指定一个primary
User user = applicationContext.getBean(User.class);
System.out.println("实时查找:" + user);
}
}
Spring IoC 依赖注入及依赖来源
META-INF/dependency-injection-context.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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<!-- 通过导入复用 dependency-lookup-context.xml -->
<import resource="dependency-lookup-context.xml"/>
<bean id="userRepository" class="com.fly.demo.UserRepository"
autowire="byType"> <!-- Auto-Wiring -->
<!-- 手动配置 -->
<!-- <property name="users">-->
<!-- <util:list>-->
<!-- <ref bean="superUser" />-->
<!-- <ref bean="user" />-->
<!-- </util:list>-->
<!-- </property>-->
</bean>
</beans>
import com.fly.demo.UserRepository;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.env.Environment;
/**
* 依赖注入示例
*/
public class DependencyInjectionDemo {
public static void main(String... args) {
String location = "classpath:/META-INF/dependency-injection-context.xml";
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext(location);
UserRepository userRepository = applicationContext.getBean("userRepository", UserRepository.class);
// 依赖来源一:自定义 Bean
// System.out.println(userRepository.getUsers());
// 依赖来源二:依赖注入(內建依赖)
System.out.println(userRepository.getBeanFactory());
System.out.println(userRepository.getBeanFactory() == applicationContext);
System.out.println(userRepository.getBeanFactory() == applicationContext.getBeanFactory());
// No qualifying bean of type 'org.springframework.beans.factory.BeanFactory' available
// System.out.println(applicationContext.getBean(BeanFactory.class));
// 依赖来源三:容器內建 Bean
Environment environment = applicationContext.getBean(Environment.class);
System.out.println("获取 Environment 类型的 Bean:" + environment);
}
}