当前位置 : 首页 » 文章分类 :  开发  »  Java面试准备-(07)Spring

Java面试准备-(07)Spring

Spring面试准备笔记


Spring

Spring DI/IOC(反射)

在Spring的工作方式中,所有的类都会在spring容器中登记,告诉spring这是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。

依赖注入的思想是通过反射机制实现的,在实例化一个类时,它通过反射调用类中set方法将事先保存在HashMap中的类属性注入到类中。 总而言之,在传统的对象创建方式中,通常由调用者来创建被调用者的实例,而在Spring中创建被调用者的工作由Spring来完成,然后注入调用者,即所谓的依赖注入or控制反转。 注入方式有两种:依赖注入和设置注入; IoC的优点:降低了组件之间的耦合,降低了业务对象之间替换的复杂性,使之能够灵活的管理对象。


Spring AOP(代理)

AOP实现的关键在于AOP框架自动创建的AOP代理,AOP代理主要分为静态代理和动态代理

  • 静态代理的代表为AspectJ;
  • 而动态代理则以Spring AOP为代表。

AspectJ(静态代理)

AspectJ是静态代理的增强,所谓的静态代理就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强。
它会在编译阶段将Aspect织入Java字节码中, 即修改目标类的.class文件,将相关代码加入其中,运行的时候就是经过增强之后的AOP对象。

Spring AOP(动态代理)

与AspectJ的静态代理不同,Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。

Spring AOP中的动态代理主要有两种方式:

  • JDK动态代理
  • CGLIB动态代理

JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。

如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

Spring AOP的实现原理
http://www.importnew.com/24305.html


Spring事务

什么是声明式事务?

声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。

如何使用声明式事务?

Spring事务在spring-tx-xxx.jar包中,spring所有的事务管理策略类都继承自org.springframework.transaction.PlatformTransactionManager 接口。
其中TransactionDefinition接口中定义了事务的传播属性和隔离级别标志。

声明式事务管理也有两种常用的方式:
1、一种是基于tx和aop名字空间的xml配置文件
2、另一种就是基于@Transactional注解。
显然基于注解的方式更简单易用,更清爽。

spring事物配置,声明式事务管理和基于@Transactional注解的使用
https://blog.csdn.net/bao19901210/article/details/41724355

@Transactional注解的用法

@Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。

虽然 @Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。另外, @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。

默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。

spring事物配置,声明式事务管理和基于@Transactional注解的使用
https://blog.csdn.net/bao19901210/article/details/41724355

@Transactional工作原理


那么Spring是如何在我们书写的 CRUD 之前和之后开启事务和关闭事务的呢?解决这个问题,也就可以从整体上理解Spring的事务管理实现原理了。下面简单地介绍下,注解方式为例子
1、配置文件开启注解驱动,在相关的类和方法上通过注解@Transactional标识。
2、spring 在启动的时候会去解析生成相关的bean,这时候会查看拥有相关注解的类和方法,并且为这些类和方法生成代理,并根据@Transaction的相关参数进行相关配置注入,这样就在代理中为我们把相关的事务处理掉了(开启正常提交事务,异常回滚事务)。
3、真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。

深入理解 Spring 事务原理
https://www.cnblogs.com/fjdingsd/p/5632949.html


Spring事务的隔离级别(默认读已提交)

隔离级别是指若干个并发的事务之间的隔离程度。
TransactionDefinition 接口中定义了五个表示隔离级别的常量:

  • TransactionDefinition.ISOLATION_DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED。

  • TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。

  • TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。

  • TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。

  • TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

spring事物配置,声明式事务管理和基于@Transactional注解的使用
https://blog.csdn.net/bao19901210/article/details/41724355


Spring事务的传播属性

事务的传播行为(propagation behavior)。当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。

所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。

Spring定义了七种传播行为:
TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。

spring事物配置,声明式事务管理和基于@Transactional注解的使用
https://blog.csdn.net/bao19901210/article/details/41724355


Spring事务嵌套

假设外层事务 Service A 的 Method A() 调用 内层Service B 的 Method B()

PROPAGATION_REQUIRED(spring 默认)
如果ServiceB.methodB() 的事务级别定义为 PROPAGATION_REQUIRED,那么执行 ServiceA.methodA() 的时候spring已经起了事务,这时调用 ServiceB.methodB(),ServiceB.methodB() 看到自己已经运行在 ServiceA.methodA() 的事务内部,就不再起新的事务。
假如 ServiceB.methodB() 运行的时候发现自己没有在事务中,他就会为自己分配一个事务。
这样,在 ServiceA.methodA() 或者在 ServiceB.methodB() 内的任何地方出现异常,事务都会被回滚。

PROPAGATION_REQUIRES_NEW
比如我们设计 ServiceA.methodA() 的事务级别为 PROPAGATION_REQUIRED,ServiceB.methodB() 的事务级别为 PROPAGATION_REQUIRES_NEW。
那么当执行到 ServiceB.methodB() 的时候,ServiceA.methodA() 所在的事务就会挂起,ServiceB.methodB() 会起一个新的事务,等待 ServiceB.methodB() 的事务完成以后,它才继续执行。

他与 PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为 ServiceB.methodB() 是新起一个事务,那么就是存在两个不同的事务。如果 ServiceB.methodB() 已经提交,那么 ServiceA.methodA() 失败回滚,ServiceB.methodB() 是不会回滚的。如果 ServiceB.methodB() 失败回滚,如果他抛出的异常被 ServiceA.methodA() 捕获,ServiceA.methodA() 事务仍然可能提交(主要看B抛出的异常是不是A会回滚的异常)。

PROPAGATION_SUPPORTS
假设ServiceB.methodB() 的事务级别为 PROPAGATION_SUPPORTS,那么当执行到ServiceB.methodB()时,如果发现ServiceA.methodA()已经开启了一个事务,则加入当前的事务,如果发现ServiceA.methodA()没有开启事务,则自己也不开启事务。这种时候,内部方法的事务性完全依赖于最外层的事务。

深入理解 Spring 事务原理
https://www.cnblogs.com/fjdingsd/p/5632949.html


事务传播的实现原理(ThreadLocal中的连接)

事务传播机制看似神奇,实际上是使用简单的ThreadLocal的机制实现的,所以如果调用的方法是在新线程调用的,事务传播实际上是会失效的;

spring在底层数据源的基础上,利用 ThreadLocal,SavePoint等技术点实现了多种事务传播属性,便于实现各种复杂的业务。只有理解了传播属性的原理才能更好的驾驭spring事务。Spring回滚事务依赖于对异常的捕获,默认情况下,只有抛出RuntimeException和Error才会回滚事务,当然可以进行配置,更多信息可以查看 @Transactional 这个注解。

spring事务-说说Propagation及其实现原理
https://blog.csdn.net/yanyan19880509/article/details/53041564/


Spring事务何时回滚?(抛出运行时异常时)

指示spring事务管理器回滚一个事务的推荐方法是在当前事务的上下文内抛出异常。spring事务管理器会捕捉任何未处理的异常,然后依据规则决定是否回滚抛出异常的事务。

认配置下,spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会导致事务回滚),而抛出checked异常则不会导致事务回滚。可以明确的配置在抛出那些异常时回滚事务,包括checked异常。也可以明确定义那些异常抛出时不回滚事务。还可以编程性的通过setRollbackOnly()方法来指示一个事务必须回滚,在调用完setRollbackOnly()后你所能执行的唯一操作就是回滚。

spring事物配置,声明式事务管理和基于@Transactional注解的使用
https://blog.csdn.net/bao19901210/article/details/41724355


Spring事务的切面(环绕切面)

事务的切面是一个“around(环绕)”切面,在注解的业务方法前后都可以被调用。实现切面的具体类是TransactionInterceptor。

事务的切面有两个主要职责:

在’ before’时,切面提供一个调用点,来决定被调用业务方法应该在正在进行事务的范围内运行,还是开始一个新的独立事务。
在’after’时,切面需要确定事务被提交,回滚或者继续运行。
在’before’时,事务切面自身不包含任何决策逻辑,是否开始新事务的决策委派给事务管理器完成。

Spring @Transactional工作原理
http://www.importnew.com/12300.html


事务管理器

事务管理器需要解决下面两个问题:
新的Entity Manager是否应该被创建?
是否应该开始新的事务?

这些需要事务切面’before’逻辑被调用时决定。事务管理器的决策基于以下两点:
事务是否正在进行
事务方法的propagation属性(比如REQUIRES_NEW总要开始新事务)

如果事务管理器确定要创建新事务,那么将:
创建一个新的entity manager
entity manager绑定到当前线程
从数据库连接池中获取连接
将连接绑定到当前线程

使用ThreadLocal变量将entity manager和数据库连接都绑定到当前线程。

事务运行时他们存储在线程中,当它们不再被使用时,事务管理器决定是否将他们清除。

程序的任何部分如果需要当前的entity manager和数据库连接都可以从线程中获取。

Spring @Transactional工作原理
http://www.importnew.com/12300.html


Java JPA(持久化API)

JPA(Java Persistence API)JAVA持久化API定义了对象-关系映射(ORM)以及实体对象持久化的标准接口。
JPA由EJB 3.0软件专家组开发,作为JSR-220实现的一部分。但它又不限于EJB 3.0,可以作为POJO持久化的标准规范,可以脱离容器独立运行,开发,测试。
JPA是一种规范,而Hibernate和iBATIS等是开源持久框架,是JPA的一种实现。

JPA的总体思想和现有Hibernate、TopLink,JDO等ORM框架大体一致。总的来说,JPA包括以下3方面的技术:
1、ORM映射元数据,JPA支持XML和JDK 5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
2、JPA的API,用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。
3、查询语言,这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。

使用 Spring Data JPA 简化 JPA 开发
https://www.ibm.com/developerworks/cn/opensource/os-cn-spring-jpa/

JPA和Hibernate的关系

JPA是需要Provider来实现其功能的,Hibernate就是JPA Provider中很强的一个。从功能上来说,JPA现在就是Hibernate功能的一个子集。可以简单的理解为JPA是标准接口,Hibernate是实现。


Spring 源码

随笔分类 - spring
http://www.cnblogs.com/xiaoxi/category/891936.html
AOP 的利器:ASM 3.0 介绍
https://www.ibm.com/developerworks/cn/java/j-lo-asm30/index.html


Spring加载

Spring加载可以利用ServletContextListener实现,也可以采用load-on-startup Servlet 实现,但是当filter需要用到bean时,由于加载顺序是:先加载filter后加载servlet,则filter中初始化操作中的bean为null;所以,如果过滤器中要使用到bean,此时就可以根据加载顺序listener -> filter -> servlet,将spring的加载改成Listener的方式。

利用监听器ContextLoaderListener加载Spring

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

其中ContextLoaderListener的作用就是启动Web容器时,自动装配applicationContext.xml的配置信息,执行它所实现的方法。

利用启动时初始化的Servlet加载Spring

<servlet>
    <servlet-name>context</servlet-narne>
    <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

Spring bean生命周期

Spring Bean的生命周期简单易懂。在一个bean实例被初始化时,需要执行一系列的初始化操作以达到可用的状态。同样的,当一个bean不在被调用时需要进行相关的析构操作,并从bean容器中移除。

Spring bean的创建和销毁

Spring bean什么时候被实例化?

Spring什么时候实例化bean,首先要分2种情况
第一:如果你使用BeanFactory作为Spring Bean的工厂类,则所有的bean都是在第一次使用该Bean的时候实例化
第二:如果你使用ApplicationContext作为Spring Bean的工厂类,则又分为以下几种情况:
(1):如果bean的scope是singleton的,并且lazy-init为false(默认是false,所以可以不用设置),则ApplicationContext启动的时候就实例化该Bean,并且将实例化的Bean放在一个map结构的缓存中,下次再使用该Bean的时候,直接从这个缓存中取
(2):如果bean的scope是singleton的,并且lazy-init为true,则该Bean的实例化是在第一次使用该Bean的时候进行实例化
(3):如果bean的scope是prototype的,则该Bean的实例化是在第一次使用该Bean的时候进行实例化

spring的bean到底在什么时候实例化
http://www.iteye.com/problems/93479

Spring如何保证创建的bean不被垃圾回收

Spring bean在程序结束时被销毁,期间不会被垃圾回收机制回收

Spring如何保证创建的bean不被垃圾回收?
JVM通过可达性分析来判定对象是否存活。这个算法的基本思路就是通过一系列称为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。将会被判定为是可回收的对象。

在Java语言中,可作为GC Roots的对象包括下面几种:
1、虚拟机栈(栈帧中的本地变量)中引用的对象。
2、方法区中类静态属性引用的对象。
3、方法区中常量引用的对象。
4、本地方法栈中JNI(Native方法)引用的对象。

spring创建对象是通过实现接口BeanFactory的类来实现的
对象存放在一个Map中:

private final Map<String, Object> singletonObjects = new HashMap();
private final Map<String, Object> beans;

其中singletonObjects是用来存放单例对象的。singletonObjects和beans(在构造方法中new)都是直接使用关键字new创建,是强引用,满足作为GC Roots对象的条件(虚拟机栈(栈帧中的本地变量)中引用的对象)。这样创建的对象存在map中和GC Roots对象相连,所以不会被回收。

spring启动后保证创建的对象不被垃圾回收器回收
http://www.jb51.net/article/93933.htm

可在bean创建后和销毁前被调用的方法

Spring bean factory 负责管理在spring容器中被创建的bean的生命周期。Bean的生命周期由两组回调(call back)方法组成。
1、初始化之后调用的回调方法。
2、销毁之前调用的回调方法。

Spring框架提供了以下四种方式来管理bean的生命周期事件:
1、InitializingBean和DisposableBean回调接口
2、针对特殊行为的其他Aware接口
3、在bean的配置文件中指定init-method和destroy-method方法
4、@PostConstruct和@PreDestroy注解方式

实现InitializingBean和DisposableBean接口

这两个接口都只包含一个方法。通过实现InitializingBean接口的afterPropertiesSet()方法可以在Bean属性值设置好之后做一些操作,实现DisposableBean接口的destroy()方法可以在销毁Bean之前做一些操作。

public class GiraffeService implements InitializingBean,DisposableBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("执行InitializingBean接口的afterPropertiesSet方法");

    }

    @Override
    public void destroy() throws Exception {
        System.out.println("执行DisposableBean接口的destroy方法");
    }
}

这种方法比较简单,但是不建议使用。因为这样会将Bean的实现和Spring框架耦合在一起。

在bean的配置文件中指定init-method和destroy-method方法

Spring允许我们创建自己的init方法和destroy方法,只要在Bean的配置文件中指定init-method和destroy-method的值就可以在Bean初始化时和销毁之前执行一些操作。
如下:

public class GiraffeService {
    //通过<bean>的destroy-method属性指定的销毁方法
    public void destroyMethod() throws Exception {
        System.out.println("执行配置的destroy-method");
    }

    //通过<bean>的init-method属性指定的初始化方法
    public void initMethod() throws Exception {
        System.out.println("执行配置的init-method");
    }

}

配置文件中的配置:

<bean name="giraffeService" class="com.giraffe.spring.service.GiraffeService" init-method="initMethod" destroy-method="destroyMethod">
</bean>

需要注意的是自定义的init-method和post-method方法可以抛异常但是不能有参数。
这种方式比较推荐,因为可以自己创建方法,无需将Bean的实现直接依赖于spring的框架。

使用@PostConstruct和@PreDestroy注解

除了xml配置的方式,Spring也支持用@PostConstruct和 @PreDestroy注解来指定init和destroy方法。这两个注解均在javax.annotation包中。
为了注解可以生效,需要在配置文件中定义org.springframework.context.annotation.CommonAnnotationBeanPostProcessor或context:annotation-config

public class GiraffeService {
    @PostConstruct
    public void initPostConstruct(){
        System.out.println("执行PostConstruct注解标注的方法");
    }

    @PreDestroy
    public void preDestroy(){
        System.out.println("执行preDestroy注解标注的方法");
    }

}

配置文件

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />

【Spring】Bean的生命周期
http://www.importnew.com/22350.html

Spring Bean生命周期详解
http://blog.csdn.net/a327369238/article/details/52193822


Spring 注解

Spring系列之Spring常用注解总结
https://www.cnblogs.com/xiaoxi/p/5935009.html

详解 Spring 3.0 基于 Annotation 的依赖注入实现
https://www.ibm.com/developerworks/cn/opensource/os-cn-spring-iocannt/

@Component扫描(@Repository @Service @Controller)

@Component把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>
如果@Controller不指定其value【@Controller】,则默认的bean名字为这个类的类名首字母小写,如果指定value【@Controller(value=”UserAction”)】或者【@Controller(“UserAction”)】,则使用value作为bean的名字。

如何开启自动扫描:

<context:component-scan base-package="xxx" />

spring会自动扫描xxx路径下的注解。

@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

  • @Service用于标注业务层组件、
  • @Controller用于标注控制层组件(如struts中的action)
  • @Repository用于标注数据访问组件,即DAO组件。

@Scope(Spring中bean的作用域)

在 Spring IoC 容器中具有以下几种作用域:基本作用域(singleton、prototype),Web 作用域(reqeust、session、globalsession),自定义作用域。

singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例
prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例
request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效
session:对于每次HTTP Session,使用session定义的Bean都将产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效
global-session:global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。

默认是单例模式,即scope=”singleton”。
另外scope还有prototype、request、session、global session作用域。
scope=”prototype”多例
1.singleton单例模式,全局有且仅有一个实例
2.prototype原型模式,每次获取Bean的时候会有一个新的实例


@Autowired @Qualifier(“xx”)自动装配

@Autowired顾名思义,就是自动装配,其作用是为了消除代码Java代码里面的getter/setter与bean属性中的property。当然,getter看个人需求,如果私有属性需要对外提供的话,应当予以保留。
@Autowired默认按类型匹配的方式,在容器查找匹配的Bean,当有且仅有一个匹配的Bean时,Spring将其注入@Autowired标注的变量中。

@Autowired 默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。如下: @Autowired @Qualifier(“beanName”) 存在多个实例配合使用

Setter方法上的@Autowired

您可以在setter方法上使用@Autowired注释来摆脱XML配置文件中的<property>元素。当Spring发现使用setter方法的@Autowired注释时,它会尝试在方法上执行autowire=”byType”的自动连接。

属性上的@Autowired

您可以在属性上使用@Autowired注解来摆脱setter方法。当你使用<property>传递自动连线属性的值时,Spring将自动为传递的值或引用分配这些属性。

构造函数上的@Autowired

您也可以将@Autowired应用于构造函数。构造函数@Autowired注解表示构造函数在创建bean时应该是自动连线的,即使在XML文件中配置bean时不使用<constructor-arg>元素也可以。

Spring的@Autowired注解
https://www.cnblogs.com/EasonJim/p/6895486.html

@Resource(name=”x”)自动装配

@Resource注解与@Autowired注解作用非常相似
说一下@Resource的装配顺序:
(1)、@Resource后面没有任何内容,默认通过name属性去匹配bean,找不到再按type去匹配
(2)、指定了name或者type则根据指定的类型去匹配bean
(3)、指定了name和type则根据指定的name和type去匹配bean,任何一个不匹配都将报错

@Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。

@Required 修饰set表示必须注入

用在set方法上,一旦用了这个注解,那么容器在初始化bean的时候必须要进行set,也就是说必须对这个值进行依赖注入。

Spring @Required 注释
http://wiki.jikexueyuan.com/project/spring/annotation-based-configuration/spring-required-annotation.html


Spring和Spring Boot区别

Spring boot是一个在Spring 的基础上搭建的全新的微框架,其目的是简化Spring的搭建和开发过程。

Spring Boot可以以jar包的形式来运行,运行一个Spring Boot项目我们只需要通过java -jar xx.jar类运行。非常方便。

Spring Boot主要特性
(1)遵循“习惯优于配置”的原则,使用Spring Boot只需要很少的配置,大部分的时候我们直接使用默认的配置即可;
(2)项目快速搭建,可以无需配置的自动整合第三方的框架;
(3)可以完全不使用XML配置文件,只需要自动配置和Java Config;
(4)内嵌Servlet容器,降低了对环境的要求,可以使用命令直接执行项目,应用可用jar包执行:java -jar;
(5)提供了starter POM, 能够非常方便的进行包管理, 很大程度上减少了jar hell或者dependency hell;
(6)运行中应用状态的监控;
(7)对主流开发框架的无配置集成;
(8)与云计算的天然继承;

为什么越来越多的开发者选择使用Spring Boot
http://blog.csdn.net/xlgen157387/article/details/52830071


上一篇 MySQL-Windows安装

下一篇 Java面试准备-(06)Redis和缓存

阅读
7,375
阅读预计27分钟
创建日期 2018-04-18
修改日期 2018-11-20
类别
百度推荐