Spring的理解
Spring是一个IOC和AOP的容器框架
Spring容器的主要核心是:
- 控制反转(IOC),传统的java开发模式中,当需要一个对象时,我们会自己使用new或者getInstance等直接或间接调用构造方法来创建一个对象。而在Spring开发模式中,不需要我们自己创建了,直接调用spring提供的对象就可以了,这是控制反转思想。
- 依赖注入(DI),spring使用javaBean对象的set方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程,就是依赖注入的思想。
- 面向切面编程(AOP),在面向对象编程(OOP)思想中,我们将事物纵向轴抽成一个个个对象。而在面向切面编程中,我们将一个个的对象某些相似的方面横向抽成一个切面,对这个切面进行一些如权限控制,事物管理,记录日志等公用操作处理过程就是面向切面编程的思想。AOP底层是动态代理,如果是接口采用JDK动态代理,如果是类采用CGLIB方式实现动态代理。
bean的三种实例化方式
-
构造
- 通过无参构造器实例化(默认):
- 有参构造器:构造器,public CstCuseomer (Long custId,String custName)
-
静态工厂 ,class:配置工厂类的路径, factory-method:调用工厂方法,获取对象。
-
实例工厂
bean的生命周期
-
单例
- 通过配置标签上的init-method作为bean的初始化的时候执行的方法,配置destory-method,作为Bean的销毁的时候执行的方法。销毁方法想要执行,需要是单例创建的Bean,而且在工厂关闭的时候Bean才会被销毁。
- 出生:容器创建
- 活着:容器还在,对象就一直活着
- 死亡:容器没了,对象就消亡了
-
多例
- 出生:什么时候用(getBean),什么时候就创建
- 活着:只要对象被使用,该对象就一直活着
- 死亡:有垃圾回收器管理
bean什么时候实例化
spring什么时候实例化bean,首先要分为2种情况,
第一:如果使用BeanFactory作为spring Bean的工厂类,则所有的bean都是在第一次使用的时候实例化
第二:如果你用的是application context作为Spring Bean的工厂类,又分为以下几种情况.
(1):如果bean的scope是singleton的,并且lazy-init为false,则application context启动的时候就实例化该bean,并且将实例化的bean放在一个map结构的缓存中,下次再使用,从缓存中去
(2):如果bean的scope是singleton的,并且lazy-init为true,则该bean的实例化是在第一次使用的该bean的时候进行实例化
(3):如果该bean的scope是prototype的,则该bean的实例化是第一次使用该bean的时候创建。
bean的作用域
-
singleton默认值
- 单例,系统在运行中只有一个实例,在加载spring容器时候将bean实例化好,只实例一次。默认非懒加载。
- Dao:单例,在dao不要添加具有状态的属性(数据域的成员变量)
- Service:单例,在Service不要添加具有状态的属性(数据域的成员变量)
- Action:多例
- Servlet:单例
-
prototype
- 多例,每次访问都要创建一个实例
- 调用applicationContext.getBean方法时,都会创建一个实例
-
request
- 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境;
- :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中.
-
session
- 同一个HTTP Session 共享一个Bean,不同Session使用不用Bean,仅适用于WebApplicationContext环境、
- WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中.
-
globalSession
- 一般用于Porlet应用环境,该作用域仅适用于WebApplicationContext环境;
- :WEB 项目中,应用在 Porlet 环境.如果没有 Porlet 环境那么 globalSession 相当 于 session.
ApplicationContext
-
spring容器的上下文,通过上下文操作容器中bean,applicationContext.getBean(“customerDao”)
-
加载文件
- ClassPathXmlApplicationContext:加载classpath下的配置文件创建一个容器实例
- FileSystemXmlApplicationContext:加载classpath下的配置文件创建一个容器实例
- 多文件的加载方法(掌握)
- //加载多个配置文件
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext(new String[]{“bean1.xml”,“bean2.xml”});
- //通过统配符号加载
- 第一种 ApplicationContext applicationContext = new ClassPathXmlApplicationContext(“classpath:bean*.xml”);
- 第二种 ApplicationContext applicationContext = new ClassPathXmlApplicationContext(new String[]{“bean1.xml”,“classpath:bean*.xml”});
- //加载多个配置文件
spring注解
- @Repository:标识此bean为一个dao
- @Service:标识此bean为一个Service
- @Controller:标识此bean为一个Controller
- 在spring中提供了@component标识就是一个bean。@Component可以用在任何的bean上。
- @Scope:prototype:多例,使用Singleton:单例(默认单例)
- @Autowired与@Qualifeier:按类型注入
- 如果容器中同一个类型的bean如果有多个,使用Autowired会报错,应该搭配Qualifier使用,Qualifier指定将哪个bean注入进来(id/name)。
@Resource:按名称注入
- 如果容器中同一个类型的bean如果有多个,使用Autowired会报错,应该搭配Qualifier使用,Qualifier指定将哪个bean注入进来(id/name)。
@Resource和autoWired区别:Resource注解是jdk下的,而autoWired是spring提供。
spring事务
声明式事务管理的定义:用在Spring配置文件中声明式的处理事务来代替代码式的处理事务。这样的好处是,事务管理不侵入开发的组件,具体来说,业务逻辑对象就不会意识到正在事务管理之中,事务上也应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策划的话,也只需要在定义文件中重新配置1即可,这样维护比较方便。
BeanFactory常用的实现类有
Bean 工厂是工厂模式的一个实现,提供了控制反转功能,用来把应用的配置和依赖从正真的应用代码中分离。常用的BeanFactory实现有DefaultListableBeanFactory,XmlBeanFactory,ApplicationContext等。XMLBeanFactory最常用的就是 org.springframework.beans.factory.xml.XmlBeanFactory ,它根据xml文件中
定义加载beans。该容器从xml文件读取配置元是数据并用它去创建一个完全配置的系统或应用。
ApplicationContext的实现类有
FileSystemXmlApplicationContext:此容器从一个xml文件中加载beans的定义,xml bean配置文件的全路径名必须提供给它的构造函数
ClassPathXmlApplicationContext:此容器也从一个XML文件中加载beans的定义,这里,你需要正确设置classpath 因为这个容器将在 classpath 里找 bean 配置。
WebXmlApplicationContext:此容器加载一个XML文件,此文件定义了一个WEB应用的所有bean。
BeanFactory与ApplicationContext的区别
- BeanFactory
基础类型的IOC容器,提供完成的IOC服务。如果没有特殊指定,默认采用延迟初始化策略。相对来说,容器启动初期速度较快,所需资源有限。 - ApplicationContext
ApplicationContext是在BeanFactory的基础上构建,是相对比较高级的容器实现,除了BeanFactory的所有支持外,ApplicationContext还提供了事件的发布,国际化支持等功能。ApplicationContext 管理的对象,在容器启动后默认全部初始化并且绑定完成。
哪些不同的IOC方法?
- set注入
- 构造器注入
- 静态工厂的方法注入
- 实例工厂的注入
Spring框架中的单例bean是线程安全的吗?
不安全,解决办法
- 需要的时候创建新的实例
- 使用同步:synchronized
- 使用ThreadLocal
- ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的 变量副本 。解决了变量并发访问的冲突问题。
- 使用ThreadLocal, 也是将共享变量变为独享,线程独享肯定能比方法独享在并发环境中能减少不少创建对象的开销。如果对性能要求比较高的情况下,一般推荐使用这种方法。
spring如何注入一个java集合
- 类型用于注入一列值,允许有相同的值。
- 类型用于注入一组值,不允许有相同的值。
- 类型用于注入一组键值对,键和值都只能为 String 类型。