Spring
1.IOC(DI) - 控制反转(依赖注入) —低耦合
所谓的IOC称之为控制反转,简单来说就是将对象的创建的权利及对象的生命周期的管理过程交由Spring框架来处理,从此在开发过程中不再需要关注对象的创建和生命周期的管理,而是在需要时由Spring框架提供,这个由spring框架管理对象创建和生命周期的机制称之为控制反转。而在 创建对象的过程中Spring可以依据配置对对象的属性进行设置,这个过称之为依赖注入,也即DI
IOC实现原理:
在初始化一个Spring容器时,Spring会去解析指定的xml文件,当解析到其中的标签时,会根据该标签中的class属性指定的类的全路径名,通过反射创建该类的对象,并将该对象存入内置的Map中管理。其中键就是该标签的id值,值就是该对象。
之后,当通过getBean方法来从容器中获取对象时,其实就是根据传入的条件在内置的Map中寻找是否有匹配的键值,如果有则将该键值对中保存的对象返回,如果没有匹配到则抛出异常。
推论:
默认情况下多次获得相同id的bean 拿到的是同一个对象
不可以配置多个id相同的bean
可以配置多个id不同但class相同的bean
获取bean的方式:
1. 通过id获取 但是需要强转类型 Persion p = (Persion)context.getBean("persion");
获取bean的方式1:通过id获取bean
找不到bean: 抛出异常NoSuchBeanDefinitionException
找到唯一的bean: 返回该bean
找到多个bean: 不可能找到多个,id不允许重复,如果重复了容器初始化阶段就会报错
2.
获取bean的方式2:通过class获取bean Person person = context.getBean(Person.class);
找不到bean: 抛出异常NoSuchBeanDefinitionException
找到唯一的bean: 返回该bean
找到多个bean: 可能找到多个,抛出异常NoUniqueBeanDefinitionException
Spring创建对象的方式:
1.默认通过无参构造器创建对象
2.通过指定构造器创建对象
3.通过工厂创建对象
静态工厂创建对象
实例化工厂创建对象
Spring工厂创建对象
单例和多例
Spring容器管理的bean在默认情况下是单例的,也即,一个bean只会创建一个对象,存在内置 map中,之后无论获取多少次该bean,都返回同一个对象。
Spring默认采用单例方式,减少了对象的创建,从而减少了内存的消耗。
但是在实际开发中是存在多例的需求的,Spring也提供了选项可以将bean设置为多例模式。
<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
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<!-- scope属性控制当前bean的创建模式:
singleton:则当前bean处在单例模式中,默认就是此模式
prototype:则当前bean处在多例模式中-->
<bean id="cart" class="cn.tedu.beans.Cart"scope="prototype"></bean>
</beans>
bean在单例模式下的生命周期:
bean在单例模式下,spring容器启动时解析xml发现该bean标签后,直接创建该bean的对象存入内部map中保存,此后无论调用多少次getBean()获取该bean都是从map中获取该对象返回,一直是一个对象。此对象一直被Spring容器持有,直到容器退出时,随着容器的退出对象被移除出容器。
bean在多例模式下的生命周期:
bean在多例模式下,spring容器启动时解析xml发现该bean标签后,只是将该bean进行管理,并不会创建对象,此后每次使用 getBean()获取该bean时,spring都会重新创建该对象返回,每次都是一个新的对象。这个对象spring容器并不会持有,什么时候销毁取决于用户程序本身。
懒加载机制:
Spring默认会在容器初始化的过程中,解析xml,并将单例的bean创建并保存到map中,这样的机制在bean比较少时问题不大,但一旦bean非常多时,spring需要在启动的过程中花费大量的时间来创建bean 花费大量的空间存储bean,但这些bean可能很久都用不上,这种在启动时在时间和空间上的浪费显得非常的不值得。
所以Spring提供了懒加载机制。所谓的懒加载机制就是可以规定指定的bean不在启动时立即创建,而是在后续第一次用到时才创建,从而减轻在启动过程中对时间和内存的消耗。
懒加载机制只对单例bean有作用,对于多例bean设置懒加载没有意义。
懒加载只是延后了对象创建的时机,对象仍然是单例的。
配置初始化和销毁的方法:
在Spring中如果某个bean在初始化之后 或 销毁之前要做一些
额外操作可以为该bean配置初始化和销毁的方法 ,在这些方法中完成要功能。
2.Spring DI:
IOC(DI)
- 控制反转(依赖注入)
所谓的IOC称之为控制反转,简单来说就是将对象的创建的权利及对象的生命周期的管理过程交由Spring框架来处理,从此在开发过程中不再需要关注对象的创建和生命周期的管理,而是在需要时由Spring框架提供,这个由spring框架管理对象创建和生命周期的机制称之为控制反转。而在
创建对象的过程中Spring可以依据配置对对象的属性进行设置,这个过称之为依赖注入,也即DI。
2.基于set方法注入:
a.Spring普通属性注入
b.自定义bean注入
c.自动装配····
类属性
bean属性 关键看的是get set方法
Spring注解方式 实现 IOC 和DI
1.Spring注解
Spring除了默认的使用xml配置文件的方式实现配置之外,也支持使用注解方式实现配置,这种方式效率更高,配置信息清晰,代码在哪对应的配置就在哪,方便开发阶段修改,推荐使用。
所谓注解就是给程序看的提示信息,很多时候都用来作为轻量级配置的方式。
关于注解的知识点,参看java基础课程中java基础加强部分的内容。
2.Spring注解方式实现IOC
3.Spring注解方式实现IOC - 工厂注册bean
Spring默认通过反射创建bean,如果某些bean没有无参构造器或创建过程非常复杂,则无法通过简单的反射创建bean,此时可以通过指定创建bean的工厂,令SpringIOC通过工厂来创建bean,从而进行注册。
可以通过配置文件方式配置bean工厂,同样也可以通过注解配置bean工厂。
a.
配置工厂类
工厂类必须放在包扫描目录下,且被@Component注解修饰
b.
配置工厂类中生产bean的方法
工厂中生产bean的方法要被@Bean修饰
则此方法会被SpringIOC调用,并将返回的对象注册为Spring的bean,默认自动推断id,也可以通过value属性手工指定id。
当Spring容器解析到@Component注解时,创建当前类的bean在spring容器中进行管理,在创建bean的过程中发现了@Autowired注解,会根据当前bean类型,寻找在spring中是否存在该类型的bean,找到直接注入,如果找不到还会检查是否有子孙类、实现类存在,如果存在唯一的则自动注入,如果还是没有找到或找到多个无法注入,则还会按照属性名对应id去查找对应的bean,如果存在则注入,如果还是没有找到则抛出异常。
也可以额外配置@Qualifier(value=“dog1”)注解强制要求按照id寻找bean,则此时会直接使用给定的id寻找bean,而不会进行基于类型的匹配。
其他注解:
a.@Scope(value=“prototype”)
配置修饰的类的bean是单例还是多例,如果不配置默认为单例
b.@Lazy
配置修饰的类的bean采用懒加载机制
c.@PostConstruct
在bean对应的类中 修饰某个方法 将该方法声明为初始化方法,对象创建之后立即执行。
d.@PreDestroy
在bean对应的类中 修饰某个方法 将该方法声明为销毁的方法,对象销毁之前调用的方法。
e.
@Controller
@Service
@Repository
@Component
这四个注解的功能是完全相同的,都是用来修饰类,将类声明为Spring管理的bean的。
其中@Component一般认为是通用的注解
而@Controller用在软件分层中的控制层,一般用在web层
而@Service用在软件分层中的业务访问层,一般用在service层
而@Repository用在软件分层中的数据访问层,一般用在dao层
3.AOP:
耦合:如果乱传递某一层特有的对象,造成层与层之间的关系变得过于紧密,称之为层与层之间发生了耦合
解耦:接触耦合的过程就称之为解耦
代码结构清晰便于开发维护
代码功能转义便于代码复用