目录
1.spring ioc依赖查找
通话xml的方式
新建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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="iocDemoUser" class="com.demo.ioc.spring.ioc.overview.IocDemoUser" primary="true">
<property name="name" value="jack"/>
<property name="age" value="22"/>
<property name="address" value="成都"/>
</bean>
<bean id="usaUser" class="com.demo.ioc.spring.ioc.overview.pojo.UsaUser">
<property name="name" value="usa"/>
<property name="age" value="220"/>
<property name="address" value="美国"/>
</bean>
<bean id="userObjectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
<property name="targetBeanName" value="iocDemoUser"/>
</bean>
</beans>
spring依赖查找方式有:按名称直接查找,ObjectFactory懒加载方式查找,按注解查找,以及按类型查找所有Bean
示例:
public class DependencyLookupDemo {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:META-INF/dependency-lookup-context.xml");
System.out.println("直接查找:");
lookupInRealtime(ctx);
System.out.println("lazy查找:");
lookupLazy(ctx);
System.out.println("注解查找:");
lookupByAnnotation(ctx);
System.out.println("集合查找:");
lookupCollectionByType(ctx);
}
private static void lookupCollectionByType(BeanFactory ctx) {
if (ctx instanceof ListableBeanFactory) {
ListableBeanFactory lCtx = (ListableBeanFactory) ctx;
Map<String, IocDemoUser> beansOfType = lCtx.getBeansOfType(IocDemoUser.class);
System.out.println(beansOfType);
}
}
//注解查找
private static void lookupByAnnotation(BeanFactory ctx) {
if (ctx instanceof ListableBeanFactory) {
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) ctx;
Map<String, Object> beans = listableBeanFactory.getBeansWithAnnotation(Usa.class);
System.out.println(beans);
}
}
//ObjectFactory方式懒加载查找
private static void lookupLazy(ClassPathXmlApplicationContext ctx) throws Exception {
ObjectFactory<IocDemoUser> userObjectFactory = (ObjectFactory<IocDemoUser>) ctx.getBean("userObjectFactory");
System.out.println(BeanUtils.describe(userObjectFactory));
Object object = userObjectFactory.getObject();
System.out.println(BeanUtils.describe(object));
}
//实时查找
private static void lookupInRealtime(ClassPathXmlApplicationContext ctx) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
Object user = ctx.getBean("iocDemoUser");
System.out.println(BeanUtils.describe(user));
}
}
输出:
直接查找:
{address=成都, name=jack, age=22}
lazy查找:
{object=com.demo.ioc.spring.ioc.overview.IocDemoUser@57e1b0c}
{address=成都, name=jack, age=22}
注解查找:
{usaUser=com.demo.ioc.spring.ioc.overview.pojo.UsaUser@46daef40}
集合查找:
{iocDemoUser=com.demo.ioc.spring.ioc.overview.IocDemoUser@57e1b0c, usaUser=com.demo.ioc.spring.ioc.overview.pojo.UsaUser@46daef40}
bean class
public class IocDemoUser {
private String name;
private Integer age;
private String address;
}
@Usa
public class UsaUser extends IocDemoUser {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Usa {
}
2.spring ioc依赖注入
新建dependency-injection-context.xml配置文件
<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">
<import resource="dependency-lookup-context.xml"/>
<bean id="userRepository" class="com.demo.ioc.spring.ioc.overview.repository.UserRepository"
<!--按类型注入-->
autowire="byType">
</bean>
</beans>
示例代码:
public class DependencyInjectionDemo {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:META-INF/dependency-injection-context.xml");
UserRepository userRepository = (UserRepository) ctx.getBean("userRepository");
System.out.println(userRepository);
System.out.println("ObjectFactory<ApplicationContext> : " + userRepository.getAppFactory().getObject());
System.out.println("userRepository.getBeanFactory() == ctx: " + (userRepository.getBeanFactory() == ctx));
//报错(说明依赖查找和依赖注入的范围不一样)
// ctx.getBean(BeanFactory.class);
}
}
输出:
UserRepository{userList=[com.demo.ioc.spring.ioc.overview.IocDemoUser@5bc79255, com.demo.ioc.spring.ioc.overview.pojo.UsaUser@47ef968d], beanFactory=org.springframework.beans.factory.support.DefaultListableBeanFactory@5ebec15: defining beans [iocDemoUser,usaUser,userObjectFactory,userRepository]; root of factory hierarchy, userFactory=org.springframework.beans.factory.support.DefaultListableBeanFactory$DependencyObjectProvider@4f063c0a, appFactory=org.springframework.beans.factory.support.DefaultListableBeanFactory$DependencyObjectProvider@1e6d1014}
ObjectFactory<ApplicationContext> : org.springframework.context.support.ClassPathXmlApplicationContext@300ffa5d, started on Sun Jun 13 21:47:46 CST 2021
userRepository.getBeanFactory() == ctx: false
userRepository.getAppFactory().getObject() == ctx: true
UserRepository
public class UserRepository {
private Collection<IocDemoUser> userList;
private BeanFactory beanFactory;
private ObjectFactory<IocDemoUser> userFactory;
private ObjectFactory<ApplicationContext> appFactory;
//getter and setter
}
总结:
可见spring ioc的依赖查找和依赖注入的源并不是完全相同的
依赖注入包含了三个源:
- 自定义bean
- 容器内建bean
- 容器內建依赖
从AbstractApplicationContext的refresh方法中
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
...
}
看到prepareBeanFactory中内建了很多Bean及依赖
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}