spring Ioc和DI相关

一,容器相关

Ioc(控制反转)的核心是DI(依赖注入),为了提供一种简单的方式设置组件依赖项(对象协作者),并在整个生命周期中管理这些依赖项。

概念:

1.依赖对象:需要弄些依赖对象的组件,或者叫目标对象。

控制反转的类型:

1.依赖注入:优先使用

(1)构造函数注入:在构造函数中设置需要的依赖项,也就是带参数的构造函数。如果没有依赖项无法创建对象。

注意一下如何选择构造函数就可以,比如可以指定参数类型。

(2)setter依赖注入:提供专门的setter方法设置依赖项。可以在没有依赖项的时候创建对象,然后通过setter方法设置依赖项。

@Autowired可以注释在方法(包括构造函数)上,容器会自动给参数设置依赖,根据参数名称。

(3)字段注入

@Autowried

private Inspiration inspirationBean;  最常用方式。

@value注解可以给方法参数设置初始值。

(4)查找方法注入

动态获取依赖项,可以解决单例引用非单例的情况。使用CGLIB动态代理实现。

原理:核心是使用<lookup-method>或者@Lookup,以注解方法为例。首先使用@Scope("prototype")改变依赖项的作用域为非单例,然后在目标bean中设置一个返回空的方法,并使用@Lookup注释

这样在调用这个方法的使用spring就好动态的去获取依赖项。注意容器中的bean默认都是单例模式。

(5)方法替换

动态的替换bean上的任意方法,而无需改变源代码。使用CGLIB动态代理实现。

原理:核心是使用<replaced-method name='被替换方法名称' replacer='替换bean'>,其中replacer是实现了MethodReplacer接口的类,并注册为bean。

相关说明:

   a.如果组件创建之前必须其他组件先创建就使用构造函数注入,其他的一般使用setter注入。

   b.注意组件和配置的区别,接口中一般会这种很多配置方法,而不会提供依赖项。

public interface NewsletterSender(){

      void setSmtpServer(String smtpServer);

      String getSmtpServer();

      void setFromAddress(String fromAddress);

      String getFromAddress();

      void send();

}

上面接口前四个都是配置方法,为最后一个方法提供配置,一般放到接口中可以定义出改接口的业务逻辑。但是,不要把特定的组件放到接口中,放到子类中进行声明设置。

组件和配置的区别:

(1)配置参数是被动的,一般是由其他函数调用。

(2)配置参数通常是信息,而不是组件

(3)配置参数通常是简单值或者简单值的集合。

c.setter注入可以在不创建父组件的情况下修改依赖项

2.依赖查找:

(1)依赖拉取:从JNDI注册表中拉取Bean,容器中的bean都在某个注册表中注册,获取依赖项的时候从注册表中查找。

(2)上下文依赖查找:直接从容器中获取,而不是从注册表中。组件都实现特定接口,该接口有一个特定方法可以获取到当前组件。

二:spring中的应用

1.依赖注入的核心BeanFactory接口,bean是组件。BeadFacotry管理bean的整个生命周期。

2.应用程序必须创建一个实现了BeanFactory接口的实例(常用的是ApplicationContext,需要实现BeanDefinitionReader接口,才能从配置中获取bean配置信息),并使用bean和依赖信息进行配置(bean配置由实现了BeanDefinition接口的实例表示,bean配置不仅存储bean本身信息还有它依赖的bean的信息,通常配置信息放到外部,比如xml或者property中分别对应不同的类进行加载)。

示例:

(1)

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();//创建beanfactory

XmlBeanDefinitionReadder rdr = XmlBeanDefinitionReader(factory);//创建bean配置加载类

rdr.loanBeanDefinitions(new ClassPathResource('spring/xml-bean-factory-config.xml'));//加载bean配置。

 (2)GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();

ctx.load('spring/xml-bean-factory-config.xml');//跟上面相比省掉了第二步。

3.使用Java配置

当应用第三方库,比如mybatis,的时候通常需要创建很多固定的bean,一般这些都不会在改变,这种情况可以使用Java配置。

配置类使用@Configuration注解,并包含@Bean注解的方法,这些方法由Spring Ioc 容器直接调用来实例化bean。bean名称与用于创建它的方法的名称相同

获取配置类中的bean需要使用

ApplicationContext ctx = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);

获取bean配置还有其他方式:@ComponentScan(basePackages={"com.apress.prospring5.ch3.annotation"})  @ImportResource(locations = {"classpath:spring/app-context-xml.xml"});

4.通过使用SpEL,Spring可以访问任何Spring管理的bean和属性

@Value("#{bean.property}")
5.ApplicationContext可以嵌套,也就是可以声明多个容器,并设置父子关系。并能相互使用对方容器中的bean。

6.@Autowired 如果设置的是一个集合类型对象,Spring会尝试将当前ApplicationContext中所有该类型的对象都注入进来,可能会导致意外的依赖项被注入。而如果没有改来下的bean,会抛出异常。

正确方式:

(1)@Resource(name="map")

(2)@Autowired

       @Qualifier("map")

上面的两种方式可以明确注入的bean名称,避免注入其他的依赖项。

7. bean作用域

(1)单例作用域

(2)原型作用域

(3)请求作用域:针对每个HTTP请求实例化一个bean

(4)会话作用域:针对每个HTTP会话(可能有多个请求)实例化一个bean

(5)全局会话作用域:应用程序的所有Portlet之间共享。

(6)线程作用域:每个线程实例化一个bean

(7)自定义作用域:实现org.springframwork.beans.factory.config.Scope接口

 8.bean依赖顺序设置

如果在配置中没有体现一个bean使用其他的bean,而是在代码中需要调用,那么spring会无法感知到,从而有可能造成bean无法被调用。针对这个使用注解@DependsOn("bean名称");

9.自动装配模式

(1)byName模式:根据名称进行注入

(2)byType模式:根据类型进行注入

(3)构造函数模式:跟byType功能上相同,都是根据类型,只是使用构造函数而不是setter来执行注入。而且匹配的是参数最多的构造函数。

(4)默认模式:自动在构造函数和byType模式之间选择。

说明:

(1)自动装配必须保证bean是唯一的,否则会报org.springframework.beans.factory.NoSuchBeanDefinitionException异常。

(2)如果确实有多个相同的类型bean的时候,可以使用@Qualifier("bean名称")来指定具体的bean。通常这个注解跟在@Autowired后面。

核心问题:

1.如何解决循环依赖。

关键流程:

猜你喜欢

转载自www.cnblogs.com/fymc/p/11082083.html