Spring 面试准备
一、IOC
-
1、IOC(控制反转)就是对象的控制权(创建以及依赖)从程序代码本身交给外部容器
- 理解:如果有两个类共用一个对象(比如数据库对象)那么在每一个类中都要组合进一个对象,这样创建开销比较大,销毁的时候顺序也比较复杂
- 我们在类中只定义一个对象,不创建,而是外部创建好,使用set或构造器设置即可。参考这里
- IOC实现原理就是工厂模式加反射机制
-
2、DI(依赖注入)就是由容器动态的将某个依赖关系注入到组件之中——这是控制反转的实现方式
-
3、依赖注入的两种方式:
- i 、Setter方法注入(Setter Injection)
- ii、构造器注入(Constructor Injection)
-
4、Spring中的设计模式
- i、工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
- ii、单例模式:Bean默认为单例模式。
- iii、代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
- iV、模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
- V、 观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现–ApplicationListener。
-
5、IOC的优缺点:
- 优点:资源集中管理,资源的松散耦合
- 缺点:使用反射创建对象,性能有损失
二、容器 Spring Beans
-
1、两个核心容器的联系:ApplicationContext接口作为BeanFactory的子接口,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能
-
2、区别:
- BeanFactory使用延迟加载,只有在使用到某个Bean时(调用getBean()) 才实例化
- 启动快,但是存在依赖问题时在运行时才能出现异常
- ApplicationContext在容器启动时一次性加载了所有的Bean
- 启动慢,占用内存大
- BeanFactory使用延迟加载,只有在使用到某个Bean时(调用getBean()) 才实例化
-
3、ApplicationContext 的通常实现:
- FileSystemXmlApplicationContext
- ClassPathXmlApplicationContext
- WebXmlApplicationContext
-
4、Spring Beans包含:如何创建、生命周期详情、依赖
-
5、配置方式
- i、XML文件配置:
<!-- 空值的user --> <bean id="userNoValue" class="intron.spring.entity.User"></bean> <!-- 带值的user,set方法注入 --> <bean id="user" class="intron.spring.entity.User"> <property name="name" value="张三"></property> <property name="age" value="18"></property> </bean> <!-- 全参构造,使用成员属性索引对应 --> <bean id="userOnIndex" class="intron.spring.entity.User"> <constructor-arg index="0" value="张三"></constructor-arg> <constructor-arg index="1" value="18"></constructor-arg> </bean> <!-- 全参构造,使用成员属性类型对应 --> <bean id="userOnType" class="intron.spring.entity.User"> <constructor-arg type="java.lang.String" value="张三"></constructor-arg> <constructor-arg type="int" value="18"></constructor-arg> </bean>
- ii、java配置:@configuration 注解表示这个类是一个配置类
@Configuration public class BeanConfiguration { @Bean public Account account(){ return new Account("001001001"); } @Bean public User user(Account account){ return new User("张三",18,account); } @Bean public User userNoAccount(){ return new User("张三",18,null); } }
- iii、注解配置:
- @Component,@Service,@Repository和 @Controller
@Repository public class JpaMovieFinder implements MovieFinder { // implementation elided for clarity } @Service public class SimpleMovieLister { private MovieFinder movieFinder; public SimpleMovieLister(MovieFinder movieFinder) { this.movieFinder = movieFinder; } }
- i、XML文件配置:
-
6、类的作用域:在bean中可以通过scope属性定义
- 作用域有五种:
- singleton:单例模式,所有引用(getBean引用)只有一个实例(缺省值)
- prototype:原型模式,每次引用都创建一个实例
- request
- session
- global-session
- 作用域有五种:
-
7、单例bean不是线程安全的
- Spring对一些Bean中非线程安全状态采用ThreadLocal进行处理,无状态(指不会保存数据)的bean可以多线程共享
-
8、 bean 的生命周期
-
9、Spring inner beans(内部bean)
内部bean通常是匿名的,并且scope为prototype -
10、自动装配
-
spring 配置文件中 节点的 autowire 参数可以控制 bean 自动装配的方式
- default - 默认的方式和 “no” 方式一样
- no - 不自动装配,需要使用 节点或参数
- byName - 根据名称进行装配
- byType - 根据类型进行装配
- constructor - 根据构造函数进行装配
<!-- no方式,手动配置 --> <bean id="person" class="constxiong.interview.assemble.Person" autowire="no"> <property name="fr" ref="fr"></property> </bean> <bean id="fr" class="constxiong.interview.assemble.FishingRod"></bean> <!-- byName --> <bean id="person" class="constxiong.interview.assemble.Person" autowire="byName"></bean> <!-- byType--> <bean id="person" class="constxiong.interview.assemble.Person" autowire="byType"></bean> <!-- 构造器方式--> <bean id="person" class="constxiong.interview.assemble.Person" autowire="constructor"></bean>
-
@Autowired:自动装配,默认by Type
-
@Resource:java自带的,默认by name ,名字冲突使用by Type
-
@Value(“xxx”) :设置属性值
-
三、注解
1、开启注解装配:<context:annotation-config/>
2、注解有哪些:
- @Configuration
- @Component, @Controller, @Repository, @Service
- @Bean注解,它表示此方法将要返回一个对象,作为一个bean注册进Spring应用上下文
- @Required:表明bean的属性必须在配置的时候设置
- @Autowired:默认是按照类型装配注入的
- @Resource:自动装配注解
- @Autowired和@Resource之间的区别:
- @Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)
- 可以使用@Qualifier注解实现ByName注入例如
@Autowired @Qualifier("userDao") // Autowired 可以这样搭配Qualifire 使用, //当有多个同类型的时候遮掩可以消除歧义 private UserDao userDao;
- 可以使用@Qualifier注解实现ByName注入例如
- @Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入,java 提供的注解,并非Spring提供
- @Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)
- @Autowired和@Resource之间的区别:
- @Qualifier:当您创建多个相同类型的 bean 并希望仅使用属性装配其中一个 bean 时,您可以使用@Qualifier 注解和 @Autowired 通过指定应该装配哪个确切的 bean 来消除歧义
- @RequestMapping:将特定 HTTP 请求方法映射到将处理相应请求的控制器中的特定类/方法
四、Spring数据访问
1、 使用 JdbcTemplate 简化数据库操作
2、 Spring DAO(数据访问对象)整合 JDBC,Hibernate 或 JDO 向上为一种统一的接口
3、Spring支持两种类型的事务管理:
- 编程式事务管理:这意味你通过编程的方式管理事务,给你带来极大的灵活性,但是难维护。
- 声明式事务管理:这意味着你可以将业务代码和事务管理分离,你只需用注解和XML配置来管理事务。
4、两种事务管理的对比
大多数Spring框架的用户选择声明式事务管理,因为它对应用代码的影响最小,因此更符合一个无侵入的轻量级容器的思想。声明式事务管理要优于编程式事务管理,虽然比编程式事务管理(这种方式允许你通过代码控制事务)少了一点灵活性。唯一不足地方是,最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。
5、Spring事务的本质其实就是数据库对事务的支持
6、spring 有五大隔离级别:
- ISOLATION_DEFAULT:底层数据库用什么就用什么
- 数据库的四大隔离级别
五、AOP
1、AOP(面向切面编程):作为面向对象的一种补充,用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect)。
2、作用及应用:减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理等
3、动态代理的两种方式:JDk动态代理 和 CGLIB动态代理
-
JDK动态代理只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。
-
如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
4、Spring AOP名词
- 切面(Aspect):切面是通知和切点的结合,(在哪里执行代码以及执行什么代码)
- 连接点(Join point):即定义在应用程序流程的何处插入切面的执行
- 通知(Advice):特定连接点上执行的动作
- 切入点(Pointcut):通知所要织入的一个或多个连接点
- 引入(Introduction):向现有类添加新方法或属性。
- 织入(Weaving):把切面应用到目标对象并创建新的代理对象的过程
5、Spring在运行时通知对象
6、Spring只支持方法级别的连接点(不支持代码块级的)
7、关注点(concern)和 横切关注点(cross-cutting concern):关注点是一个模块需要添加的功能,横切关注点是整个应用都会使用的,如:日志,登录验证等
8、Spring切面可以应用5种类型的通知:
- 前置通知(Before)
- 后置通知(After)
- 返回通知(After-returning )
- 异常通知(After-throwing)
- 环绕通知(Around)