网站建设培训东莞市,教做家庭菜的网站,动易网站 青春,温州鹿城网站制作报价1、如何实现一个IOC容器
#xff08;1#xff09;配置文件包扫描路径#xff1b;
#xff08;2#xff09;递归包扫描获取.class文件#xff1b;
#xff08;3#xff09;反射、确定需要交给IOC管理的类#xff1b;
#xff08;4#xff09;对需要注入的类进行依…1、如何实现一个IOC容器
1配置文件包扫描路径
2递归包扫描获取.class文件
3反射、确定需要交给IOC管理的类
4对需要注入的类进行依赖注入
配置文件中指定需要扫描的包路径定义一些注解分别表示访问控制层、业务服务层、数据持久层、依赖注入注解、获取配置文件注解从配置文件中获取需要扫描的包路径获取当前路径下的文件信息及文件夹信息我们将当前路径下所有以.class结尾的文件添加到一个set集合中进行储存获取指定注解的类并交给IOC容器定义一个map用来储存对象判断到每一个实例有没有依赖其他实例进行递归注入
2、spring是什么
spring是一个轻量级的控制反转IOC和面向切面AOP的容器框架
从大小开销方面而言Spring都是轻量级的
通过控制反转IOC技术达到松耦合的目的
提供了面向切面编程的丰富支持允许通过分离应用的业务逻辑与系统级服务进行内聚性的开发
包含并管理应用对象(Bean)的配置和生命周期这个意义上是一个容器
将简单的组件配置、组合成为复杂的应用这个意义上是一个框架
3、谈谈你对AOP的理解
系统是由许多不同的组件所组成的每一个组件各负责一块特定功能。除了实现自身核心功能之外这些组件还经常承担着额外的职责。例如日志、事务管理和安全这样的核心服务经常融入到自身具有核心业务逻辑的组件中去。这些系统服务经常被称为横切关注点因为它们会跨越系统的多个组件。当我们需要为分散的对象引入公共行为的时候OOP则显得无能为力。也就是说OOP允许你定义从上到下的关系但并不适合定义从左到右的关系。例如日志功能。 日志代码往往水平地散布在所有对象层次中而与它所散布到的对象的核心功能毫无关系。 在OOP设计中它导致了大量代码的重复而不利于各个模块的重用。 AOP将程序中的交叉业务逻辑比如安全日志事务等封装成一个切面然后注入到目标对象具体业务逻辑中去。AOP可以对某个对象或某些对象的功能进行增强比如对象中的方法进行增强可以在执行某个方法之前额外的做一些事情在某个方法执行之后额外的做一些事情
4、谈谈你对IOC的理解
容器概念、控制反转、依赖注入
ioc容器实际就是个mapkeyvalue里面存的各种对象在xml里配置的bean节点repository、service、controller、component,在项目启动的时候会读取配置文件里面的bean节点根据全限定类名使用反射创建对象放到map里。这个时候map里就有各种对象接下来我们在代码里需要用到里面的对象时再通过 DI注入autowired、resource等注解xml里bean节点内的ref属性项目启动的时候会读取xml节点ref属性根据id注入也会扫描这些注解根据类型或id注入id就是对象名。
控制反转
没有引入IOC容器之前对象A依赖于对象B那么对象A在初始化或者运行到某一点的时候自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B控制权都在自己手上。 引入IOC容器之后对象A与对象B之间失去了直接联系当对象A运行到需要对象B的时候IOC容器会主动创建一个对象B注入到对象A需要的地方。
通过前后的对比不难看出来对象A获得依赖对象B的过程,由主动行为变为了被动行为控制权颠倒过来了这就是“控制反转”这个名称的由来。
全部对象的控制权全部上缴给“第三方”IOC容器所以IOC容器成了整个系统的关键核心它起到了一种类似“粘合剂”的作用把系统中的所有对象粘合在一起发挥作用如果没有这个“粘合剂”对象与对象之间会彼此失去联系这就是有人把IOC容器比喻成“粘合剂”的由来。
依赖注入控制被反转之后获得依赖对象的过程由自身管理变为了由IOC容器注入。依赖注入是实现IOC的方法就是IOC容器在运行期间动态地将某种依赖关系注入到对象之中。
5、BeanFactory和ApplicationContext有什么区别
ApplicationContext是BeanFactory的子接口
ApplicationContext提供了更完整的功能
①继承MessageSource因此支持国际化。
②统一的资源文件访问方式。
③提供在监听器中注册bean的事件。
④同时加载多个配置文件。
⑤载入多个有继承关系上下文 使得每一个上下文都专注于一个特定的层次比如应用的web层。
6、描述一下Spring Bean的生命周期
1解析类得到BeanDefinition 2如果有多个构造方法则要推断构造方法 3确定好构造方法后进行实例化得到一个对象 4对对象中的加了Autowired注解的属性进行属性填充 5回调Aware方法比如BeanNameAwareBeanFactoryAware 6调用BeanPostProcessor的初始化前的方法 7调用初始化方法 8调用BeanPostProcessor的初始化后的方法在这里会进行AOP 9如果当前创建的bean是单例的则会把bean放入单例池 10使用bean 11Spring容器关闭时调用DisposableBean中destory()方法
7、解释一下Spring支持的几种bean的作用域
singleton默认每个容器中只有一个bean的实例单例的模式由BeanFactory自身来维护。该 对象的生命周期是与Spring IOC容器一致的但在第一次被注入时才会创建。 prototype为每一个bean请求提供一个实例。在每次注入时都会创建一个新的对象 requestbean被定义为在每个HTTP请求中创建一个单例对象也就是说在单个请求中都会复用 这一个单例对象。 session与request范围类似确保每个session中有一个bean的实例在session过期后bean 会随之失效。 applicationbean被定义为在ServletContext的生命周期中复用一个单例对象。 websocketbean被定义为在websocket的生命周期中复用一个单例对象。 global-session全局作用域global-session和Portlet应用相关。当你的应用部署在Portlet容器 中工作时它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话那么 这全局变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。
8、Spring框架中的单例Bean是线程安全的吗
Spring中的Bean默认是单例模式的框架并没有对bean进行多线程的封装处理。
如果Bean是有状态的 那就需要开发人员自己来进行线程安全的保证 简单的办法就是改变bean的作用域 把 singleton改为’‘protopyte’ 这样每次请求Bean就相当于是 new Bean() 这样就可以保证线程的安全了。
有状态就是有数据存储功能 无状态就是不会保存数据 controller、service和dao层本身并不是线程安全的只是如果只 是调用里面的方法而且多线程调用一个实例的方法会在内存中复制变量这是自己的线程的工 作内存是安全的。 Dao会操作数据库ConnectionConnection是带有状态的比如说数据库事务Spring的事务管理器 使用Threadlocal为不同线程维护了一套独立的connection副本保证线程之间不会互相影响Spring是如何保证事务获取同一个Connection的 不要在bean中声明任何有状态的实例变量或类变量如果必须如此那么就使用ThreadLocal把变量变为线程私有的如果bean的实例变量或类变量需要在多个线程之间共享那么就只能使用 synchronized、lock、CAS等这些实现线程同步的方法了。
9、Spring框架中都用到了那些设计模式
简单工厂由一个工厂类根据传入的参数动态决定应该创建哪一个产品类。
Spring中的BeanFactory就是简单工厂模式的体现根据传入一个唯一的标识来获得Bean对象但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。
工厂方法 实现了FactoryBean接口的bean是一类叫做factory的bean。其特点是spring会在使用getBean()调用获得该bean时会自动调用该bean的getObject()方法所以返回的不是factory这个bean而是这个 bean.getOjbect()方法的返回值。
单例模式保证一个类仅有一个实例并提供一个访问它的全局访问点 spring对单例的实现 spring中的单例模式完成了后半句话即提供了全局的访问点BeanFactory。但没有从构造器级别去控制单例这是因为spring管理的是任意的java对象。
适配器模式Spring定义了一个适配接口使得每一种Controller有一种对应的适配器实现类让适配器代替 controller执行相应的方法。这样在扩展Controller时只需要增加一个适配器类就完成了SpringMVC 的扩展了。
装饰器模式动态地给一个对象添加一些额外的职责。就增加功能来说Decorator模式相比生成子类更为灵活。Spring中用到的包装器模式在类名上有两种表现一种是类名中含有Wrapper另一种是类名中含有Decorator。
动态代理切面在应用运行的时刻被织入。一般情况下在织入切面时AOP容器会为目标对象创建动态的创建一个代理对象。SpringAOP就是以这种方式织入切面的。 织入把切面应用到目标对象并创建新的代理对象过程。
观察者模式spring的事件驱动模型使用的是 观察者模式 Spring中Observer模式常用的地方是listener的实现。
策略模式Spring框架的资源访问Resource接口。该接口提供了更强的资源访问能力Spring 框架本身大量使用了Resource 接口来访问底层资源。
模板方法父类定义了骨架调用哪些方法及顺序某些特定方法由子类实现。
大的好处代码复用减少重复代码。除了子类要实现的特定方法其他方法及方法调用顺序都在父类中预先写好了。refresh方法
10、Spring事务实现方式和原理以及隔离级别
在使用Spring框架时可以有两种使用事务的方式一种是编程式的一种是申明式的
Transactional注解就是申明式的。
首先事务这个概念是数据库层面的Spring只是基于数据库中的事务进行了扩展以及提供了一些能让程序员更加方便操作事务的方式。
比如我们可以通过在某个方法上增加Transactional注解就可以开启事务这个方法中所有的sql都会在一个事务中执行统一成功或失败。
在一个方法上加了Transactional注解后Spring会基于这个类生成一个代理对象会将这个代理对象作为bean当在使用这个代理对象的方法时如果这个方法上存在Transactional注解那么代理逻辑会先把事务的自动提交设置为false然后再去执行原本的业务逻辑方法如果执行业务逻辑方法没有出现异常那么代理逻辑中就会将事务进行提交如果执行业务逻辑方法出现了异常那么则会将事务进行回滚。
当然针对哪些异常回滚事务是可以配置的可以利用Transactional注解中的rollbackFor属性进行配置默认情况下会对RuntimeException和Error进行回滚。
spring事务隔离级别就是数据库的隔离级别外加一个默认级别 read uncommitted未提交读 read committed提交读、不可重复读 repeatable read可重复读 serializable可串行化
数据库的配置隔离级别是Read Commited,而Spring配置的隔离级别是Repeatable Read请问这时隔离级别是以哪一个为准 以Spring配置的为准如果spring设置的隔离级别数据库不支持效果取决于数据库
11、spring事务传播机制 多个事务方法相互调用时,事务如何在这些方法间传播
方法A是一个事务的方法方法A执行过程中调用了方法B那么方法B有无事务以及方法B对事务的要求不同都会对方法A的事务具体执行造成影响同时方法A的事务对方法B的事务执行也有影响这种影响具体是什么就由两个方法所定义的事务传播类型所决定。
REQUIRED(Spring默认的事务传播类型)如果当前没有事务则自己新建一个事务如果当前存在事务则加入这个事务
SUPPORTS当前存在事务则加入当前事务如果当前没有事务就以非事务方法执行
MANDATORY当前存在事务则加入当前事务如果当前事务不存在则抛出异常。
REQUIRES_NEW创建一个新事务如果存在当前事务则挂起该事务。
NOT_SUPPORTED以非事务方式执行,如果当前存在事务则挂起当前事务
NEVER不使用事务如果当前事务存在则抛出异常
NESTED如果当前事务存在则在嵌套事务中执行否则REQUIRED的操作一样开启一个事务 和REQUIRES_NEW的区别
REQUIRES_NEW是新建一个事务并且新开启的这个事务与原有事务无关而NESTED则是当前存在事务时我们把当前事务称之为父事务会开启一个嵌套事务称之为一个子事务。 在NESTED情况下父事务回滚时子事务也会回滚而在REQUIRES_NEW情况下原有事务回滚不会影响新开启的事务。
和REQUIRED的区别
REQUIRED情况下调用方存在事务时则被调用方和调用方使用同一事务那么被调用方出现异常时由于共用一个事务所以无论调用方是否catch其异常事务都会回滚 而在NESTED情况下被调用方发生异常时调用方可以catch其异常这样只有子事务回滚父事务不受影响
12、Spring事务什么时候会失效
spring事务的原理是AOP进行了切面增强那么失效的根本原因是这个AOP不起作用了常见情况有 如下几种 1、发生自调用类里面使用this调用本类的方法this通常省略此时这个this对象不是代理类而是UserService对象本身 解决方法很简单让那个this变成UserService的代理类即可 2、方法不是public的
Transactional 只能用于 public 的方法上否则事务不会失效如果要用在非 public 方法上可 以开启 AspectJ 代理模式。 3、数据库不支持事务 4、没有被spring管理 5、异常被吃掉事务不会回滚(或者抛出的异常没有被定义默认为RuntimeException)