Spring ioc容器 Spring Ioc依赖查找 pojo 定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public class User { private String id ; private String name; public String getId () { return id; } public void setId (String id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } @Override public String toString () { return "User{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}' ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Super public class SuperUser extends User { private String address; public String getAddress () { return address; } public void setAddress (String address) { this .address = address; } @Override public String toString () { return "SuperUser{" + "address='" + address + '\'' + "} " + super .toString(); } }
实时查找 查找方式分根据bean id 查询、根据bean类型查找。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:context ="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd" > <bean id ="user" class ="com.thinking.in.spring.ioc.domian.User" > <property name ="id" value ="123" /> <property name ="name" value ="liugd" /> </bean > </beans >
1 2 3 4 5 6 7 BeanFactory beanFactory = new ClassPathXmlApplicationContext (" classpath:META-INFO/Dependency-lookup-context.xml" );User user = (User)beanFactory.getBean("user" );System.out.println("实时查找:" +user.toString());
延时查找 ObjectFactory方式查询bean,间接通过org.springframework.beans.factory.ObjectFactory
获取bean。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:context ="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd" > <bean id ="user" class ="com.thinking.in.spring.ioc.domian.User" > <property name ="id" value ="123" /> <property name ="name" value ="liugd" /> </bean > <bean id ="objectFactory" class ="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean" > <property name ="targetBeanName" value ="user" /> </bean > </beans >
1 2 3 4 5 6 7 8 BeanFactory beanFactory = new ClassPathXmlApplicationContext (" classpath:META-INF/Dependency-lookup-context.xml" ); ObjectFactory<User> objectFactory = (ObjectFactory<User>)beanFactory.getBean("objectFactory" ); User user = objectFactory.getObject(); System.out.println("objectFactory延时查找:" +user.toString());
bean类型查找 通过ListableBeanFactory获取集合bean
1 2 3 4 5 6 7 8 BeanFactory beanFactory = new ClassPathXmlApplicationContext (" classpath:META-INF/Dependency-lookup-context.xml" );if (beanFactory instanceof ListableBeanFactory) { ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory; Map<String, User> users = listableBeanFactory.getBeansOfType(User.class); System.out.println("查找到的所有的 User 集合对象:" + users); }
java注解查询bean 根据super 注解去查询对应的bean对象。
1 2 3 4 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Super {}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:context ="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd" > <bean id ="user" class ="com.thinking.in.spring.ioc.domian.User" > <property name ="id" value ="123" /> <property name ="name" value ="liugd" /> </bean > <bean id ="objectFactory" class ="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean" > <property name ="targetBeanName" value ="user" /> </bean > <bean id ="superUser" class ="com.thinking.in.spring.ioc.domian.SuperUser" parent ="user" primary ="true" > <property name ="address" value ="北京" /> </bean > </beans >
1 2 3 4 5 6 7 8 BeanFactory beanFactory = new ClassPathXmlApplicationContext (" classpath:META-INF/Dependency-lookup-context.xml" ); if (beanFactory instanceof ListableBeanFactory) { ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory; Map<String, User> users = (Map) listableBeanFactory.getBeansWithAnnotation(Super.class); System.out.println("查找标注 @Super 所有的 User 集合对象:" + users); }
xml文件中写primary字段区分,主bean和其他bean的区别
listableBeanFactory.getBeansWithAnnotation(Class);
这个是返回的类型是Map<String,Object>类型,这块写Map<String, User>类似,是我们知道这个注解只标记在user pojo类型上面。
相关技术 解决依赖顺序,依赖继承问题:
<relativePath>../pom.xml</relativePath>
1 2 3 4 5 6 7 <parent > <artifactId > thinking-in-spring</artifactId > <groupId > com.thinking</groupId > <version > 1.0-SNAPSHOT</version > <relativePath > ../pom.xml</relativePath > </parent >
Spring ioc 依赖注入 依赖注入和依赖查找不是来自同一个来源。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:context ="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd" > <import resource ="Dependency-lookup-context.xml" /> <bean id ="userRepository" class ="com.thinking.in.spring.ioc.repository.UserRepository" autowire ="byType" > </bean > </beans >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 public class UserRepository { private Collection<User> users; private BeanFactory beanFactory; private ObjectFactory<User> userObjectFactory; private ObjectFactory<ApplicationContext> objectFactory; public Collection<User> getUsers () { return users; } public void setUsers (Collection<User> users) { this .users = users; } public BeanFactory getBeanFactory () { return beanFactory; } public void setBeanFactory (BeanFactory beanFactory) { this .beanFactory = beanFactory; } public ObjectFactory<User> getUserObjectFactory () { return userObjectFactory; } public void setUserObjectFactory (ObjectFactory<User> userObjectFactory) { this .userObjectFactory = userObjectFactory; } public ObjectFactory<ApplicationContext> getObjectFactory () { return objectFactory; } public void setObjectFactory (ObjectFactory<ApplicationContext> objectFactory) { this .objectFactory = objectFactory; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 BeanFactory beanFactory = new ClassPathXmlApplicationContext ("classpath:META-INF/Dependency-injection-context.xml" ); UserRepository userRepository = beanFactory.getBean(UserRepository.class); System.out.println(userRepository.getBeanFactory()); Environment environment = beanFactory.getBean(Environment.class); System.out.println(beanFactory == userRepository.getBeanFactory());
userRepository.getBeanFactory()获取的出来bean是org.springframework.beans.factory.support.DefaultListableBeanFactory
对象。
beanFactory获取出来的bean 是org.springframework.context.support.ClassPathXmlApplicationContext
对象。
Spring IOC 依赖来源
自定义bean
内建依赖bean对象
容器内建依赖
Spring ioc 配置元信息 bean自定义配置
基于XML文件
基于properties文件
基于Java注解
基于Java api
ioc容器配置
基于XML文件
基于Java注解
基于Java api
外部化属性配置
beanFaction和ApplicationContext谁才是Spring ioc容器? application就是beanFactory,application就是beanFaction的子接口。beanFaction是一个底层基本的ioc容器,然而application是beanFaction的一个超集。
ClassPathXmlApplicationContext
<- AbstractXmlApplicationContext
<-AbstractRefreshableConfigApplicationContext
<-AbstractRefreshableApplicationContext
<-AbstractApplicationContext
<-ConfigurableApplicationContext
<-ApplicationContext
<-BeanFactory
如果想使用beanFactory,需要通过org.springframework.context.support.AbstractRefreshableApplicationContext#getBeanFactory
获取底层beanFactory。
选用beanFactory还是Application? beanFactory方式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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" ; int beanDefinitionsCount = reader.loadBeanDefinitions(location); System.out.println("Bean 定义加载的数量:" + beanDefinitionsCount); lookupCollectionByType(beanFactory); } private static void lookupCollectionByType (BeanFactory beanFactory) { if (beanFactory instanceof ListableBeanFactory) { ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory; Map<String, User> users = listableBeanFactory.getBeansOfType(User.class); System.out.println("查找到的所有的 User 集合对象:" + users); } } }
无需处理复杂操作,直接加载bean 就可以。
application 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class AnnotationApplicationContextAsIocContainerDemo { public static void main (String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext (); applicationContext.register(AnnotationApplicationContextAsIocContainerDemo.class); applicationContext.refresh(); lookupCollectionByType(applicationContext); } @Bean public User user () { User user = new User (); user.setId("1" ); user.setName("test" ); return user; } private static void lookupCollectionByType (BeanFactory beanFactory) { if (beanFactory instanceof ListableBeanFactory) { ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory; Map<String, User> users = listableBeanFactory.getBeansOfType(User.class); System.out.println("查找到的所有的 User 集合对象:" + users); } } }
bean 刷新流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 public void refresh () throws BeansException, IllegalStateException { synchronized (this .startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } destroyBeans(); cancelRefresh(ex); throw ex; } finally { resetCommonCaches(); } } }