面试题错题解析2_spring

                                              面试题错题解析2-spring

下面哪段程序能够正确的实现了GBK编码字节流到UTF-8编码字节流的转换: 

1

byte[] src,dst;

A.dst=String.frombytes(src,”GBK”).getbytes(“UTF-8”)
B.dst=new String (src,”GBK”).getbytes(“UTF-8”)
C.dst=new String (”GBK”, src,) getbytes()
D.dst=String.encode(String.decode(src,”GBK”)), “UTF-8”)

解析:B
String(byte[] bytes, String charsetName),通过使用指定的 charset 解码指定的 byte 数组,构造一个新的String。
getBytes(String charsetName),使用指定的字符集将此String编码为 byte 序列,并将结果存储到一个新的 byte 数组中。


volatile关键字的说法错误的是
正确答案: A 

A.能保证线程安全
B.volatile关键字用在多线程同步中,可保证读取的可见性
C.JVM保证从主内存加载到线程工作内存的值是最新的
D.volatile能禁止进行指令重排序
解析:出于运行速率的考虑,java编译器会把经常经常访问的变量放到缓存(严格讲应该是工作内存)中,读取变量则从缓存中读。但是在多线程编程中,内存中的值和缓存中的值可能会出现不一致。volatile用于限定变量只能从内存中读取,保证对所有线程而言,值都是一致的。但是volatile不能保证原子性,也就不能保证线程安全。
volatile是java中的一个类型修饰符。它是被设计用来修饰被不同线程访问和修改的变量。如果不加入volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器 失去大量优化的机会。
1,可见性
    可见性指的是在一个线程中对该变量的修改会马上由工作内存(Work Memory)写回主内存(Main Memory),所以会马上反应在其它线程的读取操作中。顺便一提,工作内存和主内存可以近似理解为实际电脑中的高速缓存和主存,工作内存是线程独享的,主存是线程共享的。
2,禁止指令重排序优化
    禁止指令重排序优化。大家知道我们写的代码(尤其是多线程代码),由于编译器优化,在实际执行的时候可能与我们编写的顺序不同。编译器只保证程序执行结果与源代码相同,却不保证实际指令的顺序与源代码相同。这在单线程看起来没什么问题,然而一旦引入多线程,这种乱序就可能导致严重问题。volatile关键字就可以从语义上解决这个问题。
    注意,禁止指令重排优化这条语义直到jdk1.5以后才能正确工作。此前的JDK中即使将变量声明为volatile也无法完全避免重排序所导致的问题。所以,在jdk1.5版本前,双重检查锁形式的单例模式是无法保证线程安全的。因此,下面的单例模式的代码,在JDK1.5之前是不能保证线程安全的。


下列不属于Java语言性特点的是

正确答案: D   
A.Java致力于检查程序在编译和运行时的错误
B.Java能运行虚拟机实现跨平台
C.Java自己操纵内存减少了内存出错的可能性
D.Java还实现了真数组,避免了覆盖数据类型的可能
解析:Java还实现了真数组,避免了覆盖数据的可能。
注意,是避免数据覆盖的可能,而不是数据覆盖类型 。程序设计语言中,数组元素在内存中是一个接着一个线性存放的,通过第一个元素就能访问随后的元素,这样的数组称之为“真数组”。实现了真数组为Java语言健壮性的特点之一。

假设如下代码中,若t1线程在t2线程启动之前已经完成启动。代码的输出是()
 

public static void main(String[]args)throws Exception {
    final Object obj = new Object();
    Thread t1 = new Thread() {
        public void run() {
            synchronized (obj) {
                try {
                    obj.wait();
                    System.out.println("Thread 1 wake up.");
                } catch (InterruptedException e) {
                }
            }
        }
    };
    t1.start();
    Thread.sleep(1000);//We assume thread 1 must start up within 1 sec.
    Thread t2 = new Thread() {
        public void run() {
            synchronized (obj) {
                obj.notifyAll();
                System.out.println("Thread 2 sent notify.");
            }
        }
    };
    t2.start();
}

A. Thread 1 wake up
    Thread 2 sent notify.
B. Thread 2 sent notify
  . Thread 1 wake up
C. A、B皆有可能
D.程序无输出卡死
解析:正确答案: B 

线程间协作:wait、notify、notifyAll

在 Java 中,可以通过配合调用 Object 对象的 wait() 方法和 notify()方法或 notifyAll() 方法来实现线程间的通信。在线程中调用 wait() 方法,将阻塞等待其他线程的通知(其他线程调用 notify() 方法或 notifyAll() 方法),在线程中调用 notify() 方法或 notifyAll() 方法,将通知其他线程从 wait() 方法处返回。

Object 是所有类的超类,它有 5 个方法组成了等待/通知机制的核心:notify()、notifyAll()、wait()、wait(long)和 wait(long,int)。在 Java 中,所有的类都从 Object 继承而来,因此,所有的类都拥有这些共有方法可供使用。而且,由于他们都被声明为 final,因此在子类中不能覆写任何一个方法。

这里详细说明一下各个方法在使用中需要注意的几点。

wait()

public final void wait() throws InterruptedException,IllegalMonitorStateException

该方法用来将当前线程置入休眠状态,直到接到通知或被中断为止。在调用 wait()之前,线程必须要获得该对象的对象级别锁,即只能在同步方法或同步块中调用 wait()方法。进入 wait()方法后,当前线程释放锁。在从 wait()返回前,线程与其他线程竞争重新获得锁。如果调用 wait()时,没有持有适当的锁,则抛出 IllegalMonitorStateException,它是 RuntimeException 的一个子类,因此,不需要 try-catch 结构。

notify()

public final native void notify() throws IllegalMonitorStateException

该方法也要在同步方法或同步块中调用,即在调用前,线程也必须要获得该对象的对象级别锁,的如果调用 notify()时没有持有适当的锁,也会抛出 IllegalMonitorStateException。

该方法用来通知那些可能等待该对象的对象锁的其他线程。如果有多个线程等待,则线程规划器任意挑选出其中一个 wait()状态的线程来发出通知,并使它等待获取该对象的对象锁(notify 后,当前线程不会马上释放该对象锁,wait 所在的线程并不能马上获取该对象锁,要等到程序退出 synchronized 代码块后,当前线程才会释放锁,wait所在的线程也才可以获取该对象锁),但不惊动其他同样在等待被该对象notify的线程们。当第一个获得了该对象锁的 wait 线程运行完毕以后,它会释放掉该对象锁,此时如果该对象没有再次使用 notify 语句,则即便该对象已经空闲,其他 wait 状态等待的线程由于没有得到该对象的通知,会继续阻塞在 wait 状态,直到这个对象发出一个 notify 或 notifyAll。这里需要注意:它们等待的是被 notify 或 notifyAll,而不是锁。这与下面的 notifyAll()方法执行后的情况不同。

notifyAll()

public final native void notifyAll() throws IllegalMonitorStateException

该方法与 notify ()方法的工作方式相同,重要的一点差异是:

notifyAll 使所有原来在该对象上 wait 的线程统统退出 wait 的状态(即全部被唤醒,不再等待 notify 或 notifyAll,但由于此时还没有获取到该对象锁,因此还不能继续往下执行),变成等待获取该对象上的锁,一旦该对象锁被释放(notifyAll 线程退出调用了 notifyAll 的 synchronized 代码块的时候),他们就会去竞争。如果其中一个线程获得了该对象锁,它就会继续往下执行,在它退出 synchronized 代码块,释放锁后,其他的已经被唤醒的线程将会继续竞争获取该锁,一直进行下去,直到所有被唤醒的线程都执行完毕。

深入理解

如果线程调用了对象的 wait()方法,那么线程便会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。

当有线程调用了对象的 notifyAll()方法(唤醒所有 wait 线程)或 notify()方法(只随机唤醒一个 wait 线程),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。

优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,唯有线程再次调用 wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了 synchronized 代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。


有关下述Java代码描述正确的选项是____。

public class TestClass {
   private static void testMethod(){
        System.out.println("testMethod");
   }
   public static void main(String[] args) {
        ((TestClass)null).testMethod();
   }
}

A.编译不通过
B.编译通过,运行异常,报NullPointerException
C.编译通过,运行异常,报IllegalArgumentException
D.编译通过,运行异常,报NoSuchMethodException
E.编译通过,运行异常,报Exception
F.运行正常,输出testMethod

解析:正确答案: F   
1)此处是类对方法的调用,不是对象对方法的调用。
2)方法是static静态方法,直接使用"类.方法"即可,因为静态方法使用不依赖对象是否被创建。
null可以被强制类型转换成任意类型(不是任意类型对象),于是可以通过它来执行静态方法。
3)非静态的方法用"对象.方法"的方式,必须依赖对象被创建后才能使用,若将testMethod()方法前的static去掉,则会报 空指针异常 。此处也验证了2)的观点
当然,不管是否静态方法,都是已经存在的,只是访问方式不同。


 

AOP  OOP的区别:

1. 面向方面编程 AOP 偏重业务处理过程的某个步骤或阶段,强调降低模块之间的耦合度,使代码拥有更好的移植性。

2. 面向对象编程 (oop) 则是对业务分析中抽取的实体进行方法和属性的封装。

也可以说 AOP 是面向业务中的动词领域, OOP 面向名词领域。

AOP 的一个很重要的特点是源代码无关性,也就是说如果我们的系统中引用了 AOP 组件,即使我们把该组件去掉,系统代码也应该能够编译通过。要实现这一点,可以使用动态 proxy 模式。

下面关于spring mvc 和struts2的描述,错误的是?

A.spring mvc的入口是filter,而struts2是servlet
B.spring mvc是基于方法的设计,而struts2是基于类的设计
C.struts2有以自己的interceptor机制,spring mvc用的是独立的AOP方式
D.spring mvc的方法之间基本上独立的,独享request response数据,struts2所有Action变量是共享的
解析:A
我们从以下几个维度来区分两者的概念:
1.
  机制:spring mvc的入口是servlet,而struts2是filter。
    补充几点知识:
    《
 Filter 实现javax.servlet.Filter接口,在web.xml中配置与标签指定使用哪个Filter实现类过滤哪些URL链接。只在web启动时进行初始化操作。 filter 流程是线性的, url传来之后,检查之后,可保持原来的流程继续向下执行,被下一个filter, servlet接收等,而servlet 处理之后,不会继续向下传递。filter功能可用来保持流程继续按照原来的方式进行下去,或者主导流程,而servlet的功能主要用来主导流程。 
特点:可以在响应之前修改Request和Response的头部,只能转发请求,不能直接发出响应。filter可用来进行字符编码的过滤,检测用户 是否登陆的过滤,禁止页面缓存等》
      《
 Servlet, servlet 流程是短的,url传来之后,就对其进行处理,之后返回或转向到某一自己指定的页面。它主要用来在业务处理之前进行控制 
        《
 Listener呢?我们知道 servlet、filter都是针对url之类的,而listener是针对对象的操作的,如session的创建,session.setAttribute的发生,在这样的事件发 生时做一些事情。  

2. 性能:spring会稍微比struts快。 spring mvc是基于方法的设计  而sturts是基于类 ,每次发一次请求都会实例一个action,每个action都会被注入属性,而spring基于方法,粒度更细(粒度级别的东西比较sychronized和lock),但要小心把握像在servlet控制数据一样。 spring3 mvc是方法级别的拦截,拦截到方法后根据参数上的注解,把request数据注入进去,在spring3 mvc中,一个方法对应一个request上下文。 而struts2框架是类级别的拦截,每次来了请求就创建一个Action,然后调用setter getter方法把request中的数据注入;struts2实际上是通过setter getter方法与request打交道的;struts2中,一个Action对象对应一个request上下文。

3. 参数传递:struts是在接受参数的时候,可以用属性来接受参数,这就说明参数是让多个方法共享的。所以D是对的。

4. 设计思想上: struts更加符合oop的编程思想 , spring就比较谨慎,在servlet上扩展。

5. intercepter(拦截器)的实现机制:struts有以自己的interceptor机制, spring mvc用的是独立的AOP方式 。这样导致struts的配置文件量还是比spring mvc大,虽然struts的配置能继承,所以我觉得,就拿使用上来讲,spring mvc使用更加简洁, 开发效率Spring MVC确实比struts2高  spring mvc是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上 spring3 mvc就容易实现restful url  struts2是类级别的拦截,一个类对应一个request上下文;实现restful url要费劲,因为struts2 action的一个方法可以对应一个url;而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。spring3 mvc的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架方法之间不共享变量, 而struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码,读程序时带来麻烦。

6. 另外,spring3 mvc的验证也是一个亮点,支持JSR303, 处理ajax的请求更是方便 ,只需一个注解 @ResponseBody  ,然后直接返回响应文本即可。


在Spring框架中获取连接池可以有哪些方式?
A.DBCP数据源
B.C3P0数据源
C.Spring的数据源实现类(DriverManagerDataSource)
D.获取JNDI数据源
解析:abcd
 

四种方式,如下:

1:DBCP数据源

DBCP类包位于 <SPRING_HOME>/lib/jakarta-commons/commons-dbcp.jar,DBCP是一个依赖Jakarta commons-pool对象池机制的数据库连接池,所以在类路径下还必须包括<SPRING_HOME>/lib/jakarta-commons/commons-pool.jar。下面是使用DBCP配置oracle数据源的配置片断:

<bean id=”dataSource” class=”org.apache.commons.dbcp.BasicDataSource” destroy-method=”close”>
<property name=”driverClassName” value=” oracle.jdbc.driver.OracleDriver ” />
<property name=”url” value=”jdbc:oracle:thin:@localhost:1521:orcl ” />
<property name=”username” value=”root” />
<property name=”password” value=”1234″ />
</bean>

2:C3P0数据源

C3P0是一个开放源代码的JDBC数据源实现项目,它在lib目录中与Hibernate一起发布,实现了JDBC3和JDBC2扩展规范说明的Connection 和Statement 池。C3P0类包位于<SPRING_HOME>/lib/c3p0/c3p0-0.9.0.4.jar。下面是使用C3P0配置一个Oracle数据源:

<bean id=”dataSource” class=”com.mchange.v2.c3p0.ComboPooledDataSource” destroy-method=”close”>
<property name=”driverClassName” value=” oracle.jdbc.driver.OracleDriver ” />
<property name=”url” value=”jdbc:oracle:thin:@localhost:1521:orcl ” />
<property name=”username” value=”root” />
<property name=”password” value=”1234″ />
</bean>

3. Spring的数据源实现类(DriverManagerDataSource)

Spring本身也提供了一个简单的数据源实现类DriverManagerDataSource ,它位于org.springframework.jdbc.datasource包中。这个类实现了javax.sql.DataSource接口,但它并没有提供池化连接的机制,每次调用getConnection()获取新连接时,只是简单地创建一个新的连接。因此,这个数据源类比较适合在单元测试或简单的独立应用中使用,因为它不需要额外的依赖类。

<bean id=”dataSource” class=”org.springframework.jdbc.datasource.DriverManagerDataSource” destroy-method=”close”>
<property name=”driverClassName” value=” oracle.jdbc.driver.OracleDriver ” />
<property name=”url” value=”jdbc:oracle:thin:@localhost:1521:orcl ” />
<property name=”username” value=”root” />
<property name=”password” value=”1234″ />
</bean>

4.获取JNDI数据源

如果应用配置在高性能的应用服务器(如WebLogic或Websphere等)上,我们可能更希望使用应用服务器本身提供的数据源。应用服务器的数据源使用JNDI开放调用者使用,Spring为此专门提供引用JNDI资源的JndiObjectFactoryBean类。下面是一个简单的配置:

<bean id=”dataSource” class=”org.springframework.jndi.JndiObjectFactoryBean”>
<property name=”jndiName” value=”java:comp/env/jdbc/oracle”/>
</bean>

通过jndiName指定引用的JNDI数据源名称。

以下关于Spring的说法是正确( )
A.Spring 不能和Hibernate一样设置bean是否为延迟加载
B.在Spring配置文件中,就可以设置Bean初始化函数和消亡函数
C.属性注入只能是简单数据,构造方法注入可以是对象
D.对象的设计应使类和构件之间的耦合最小
解析:A、延迟加载有2种方法:一是hibernate提供的延迟载入机制;二是Spring框架提供的DAO模式结合Hibernate延迟加载的Web方案。故A错;
B、spring可以 在配置文件中 配置Bean初始化函数和消亡函数,故B对;
C、spring可以注入复杂的数据类型比如对象、数组、List集合、map集合、Properties等,故C错;
D、对象之间的耦合越高,维护成本越高。对象的设计应使类和构件之间的耦合最小,故D对.
综上所述,答案为B、D.

 

下面有关spring依赖注入说法错误的是?

A.IOC就是由spring来负责控制对象的生命周期和对象间的关系
B.BeanFactory是最简单的容器,提供了基础的依赖注入支持
C.ApplicationContext建立在BeanFactory之上,提供了系统构架服务
D.如果Bean的某一个属性没有注入,ApplicationContext加载后,直至第一次使用调用getBean方法才会抛出异常;而BeanFactory则在初始化自身时检验,这样有利于检查所依赖属性是否注入
解析:D
spring的IOC容器能够帮我们自动new对象,对象交给spring管之后我们不用自己手动去new对象了,也就是控制权的转让。spring使用BeanFactory来实例化、配置和管理对象,但是它只是一个接口,里面有一个getBean()方法。我们一般都不直接用BeanFactory,而是用它的实现类 ApplicationContext ,这个类会自动解析我们配置的applicationContext.xml.
Spring的IoC容器就是一个实现了BeanFactory接口的可实例化类。事实上,Spring提供了两种不同的容器:一种是最基本的BeanFactory,另一种是扩展的ApplicationContext。BeanFactory 仅提供了最基本的依赖注入支持,而 ApplicationContext 则扩展了BeanFactory ,提供了更多的额外功能。二者对Bean的初始化也有很大区别。BeanFactory当需要调用时读取配置信息,生成某个类的实例。如果读入的Bean配置正确,则其他的配置中有错误也不会影响程序的运行。而ApplicationContext 在初始化时就把 xml 的配置信息读入内存,对 XML 文件进行检验,如果配置文件没有错误,就创建所有的Bean ,直接为应用程序服务。相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

Which method is used by a servlet to place its session ID in a URL that is written to the servlet’s response output stream?

A.The encodeURL method of the HttpServletRequest interface.
B.The encodeURL method of the HttpServletResponse interface.
C.The rewriteURL method of the HttpServletRequest interface.
D.The rewriteURL method of the HttpServletResponse interface.

解析:b
HttpServletResponse 接口提供了重写 URL 的方法:public java.lang.String encodeURL(java.lang.String url) 
   该方法的实现机制为: 
    ● 先判断当前的 Web 组件是否启用 Session,如果没有启用 Session,直接返回参数 url。 
    ● 再判断客户端浏览器是否支持 Cookie,如果支持 Cookie,直接返回参数 url;如果不支持 Cookie,就在参数 url 中加入 Session ID 信息,然后返回修改后的 url。

下面有关SPRING的事务传播特性,说法错误的是?

A.PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行
B.PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就抛出异常
C.PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起
D.PROPAGATION_NESTED:支持当前事务,新增Savepoint点,与当前事务同步提交或回滚

解析:

事务属性的种类:   传播行为、隔离级别、只读和事务超时

 a)   传播行为定义了被调用方法的事务边界。

传播行为

意义

PROPERGATION_MANDATORY

表示方法必须运行在一个事务中,如果当前事务不存在,就抛出异常

PROPAGATION_NESTED

表示如果当前事务存在,则方法应该运行在一个嵌套事务中。否则,它看起来和PROPAGATION_REQUIRED 看起来没什么俩样

PROPAGATION_NEVER

表示方法不能运行在一个事务中,否则抛出异常

PROPAGATION_NOT_SUPPORTED

表示方法不能运行在一个事务中,如果当前存在一个事务,则该方法将被挂起

PROPAGATION_REQUIRED

表示当前方法必须运行在一个事务中,如果当前存在一个事务,那么该方法运行在这个事务中,否则,将创建一个新的事务

PROPAGATION_REQUIRES_NEW

表示当前方法必须运行在自己的事务中,如果当前存在一个事务,那么这个事务将在该方法运行期间被挂起

PROPAGATION_SUPPORTS

表示当前方法不需要运行在一个是事务中,但如果有一个事务已经存在,该方法也可以运行在这个事务中

b)   隔离级别

在操作数据时可能带来 3 个副作用,分别是脏读、不可重复读、幻读。为了避免这 3 中副作用的发生,在标准的 SQL 语句中定义了 4 种隔离级别,分别是未提交读、已提交读、可重复读、可序列化。而在 spring 事务中提供了 5 种隔离级别来对应在SQL 中定义的 4 种隔离级别,如下:

隔离级别

意义

ISOLATION_DEFAULT

使用后端数据库默认的隔离级别

ISOLATION_READ_UNCOMMITTED

允许读取未提交的数据(对应未提交读),可能导致脏读、不可重复读、幻读

ISOLATION_READ_COMMITTED

允许在一个事务中读取另一个已经提交的事务中的数据(对应已提交读)。可以避免脏读,但是无法避免不可重复读和幻读

ISOLATION_REPEATABLE_READ

一个事务不可能更新由另一个事务修改但尚未提交(回滚)的数据(对应可重复读)。可以避免脏读和不可重复读,但无法避免幻读

ISOLATION_SERIALIZABLE

这种隔离级别是所有的事务都在一个执行队列中,依次顺序执行,而不是并行(对应可序列化)。可以避免脏读、不可重复读、幻读。但是这种隔离级别效率很低,因此,除非必须,否则不建议使用。

 c)    只读

如果在一个事务中所有关于数据库的操作都是只读的,也就是说,这些操作只读取数据库中的数据,而并不更新数据,那么应将事务设为只读模式( READ_ONLY_MARKER ) , 这样更有利于数据库进行优化 

因为只读的优化措施是事务启动后由数据库实施的,因此,只有将那些具有可能启动新事务的传播行为(PROPAGATION_NESTED 、 PROPAGATION_REQUIRED 、 PROPAGATION_REQUIRED_NEW) 的方法的事务标记成只读才有意义。

如果使用 Hibernate 作为持久化机制,那么将事务标记为只读后,会将 Hibernate 的 flush 模式设置为FULSH_NEVER, 以告诉 Hibernate 避免和数据库之间进行不必要的同步,并将所有更新延迟到事务结束。

d)   事务超时

如果一个事务长时间运行,这时为了尽量避免浪费系统资源,应为这个事务设置一个有效时间,使其等待数秒后自动回滚。与设

置“只读”属性一样,事务有效属性也需要给那些具有可能启动新事物的传播行为的方法的事务标记成只读才有意义。


spring的PROPAGATION_REQUIRES_NEW事务,下面哪些说法是正确的?

A.内部事务回滚会导致外部事务回滚
B.内部事务回滚了,外部事务仍然可以提交
C.外部事务回滚了,内部事务也跟着回滚
D.外部事务回滚了,内部事务仍然可以提交
解析:

正确答案: B   

D错的原因: 因为外部事务回滚的时候,内部事务已经结束了,不能提交了。



 

七大模块,如下:

1. Spring Core: Core封装包是框架的最基础部分,提供IOC和依赖注入特性。这里的基础概念是BeanFactory,它提供对Factory模式的经典实现来消除对程序性单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关系和配置。

2.Spring Context: 构建于Core封装包基础上的 Context封装包,提供了一种框架式的对象访问方法,有些象JNDI注册器。Context封装包的特性得自于Beans封装包,并添加了对国际化(I18N)的支持(例如资源绑定),事件传播,资源装载的方式和Context的透明创建,比如说通过Servlet容器。

3.Spring DAO:  DAO (Data Access Object)提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码。 并且,JDBC封装包还提供了一种比编程性更好的声明性事务管理方法,不仅仅是实现了特定接口,而且对所有的POJOs(plain old Java objects)都适用。

4.Spring ORM: ORM 封装包提供了常用的“对象/关系”映射APIs的集成层。 其中包括JPAJDOHibernate 和 iBatis 。利用ORM封装包,可以混合使用所有Spring提供的特性进行“对象/关系”映射,如前边提到的简单声明性事务管理。

5.Spring AOP: Spring的 AOP 封装包提供了符合AOP Alliance规范的面向方面的编程实现,让你可以定义,例如方法拦截器(method-interceptors)和切点(pointcuts),从逻辑上讲,从而减弱代码的功能耦合,清晰的被分离开。而且,利用source-level的元数据功能,还可以将各种行为信息合并到你的代码中。

6.Spring Web: Spring中的 Web 包提供了基础的针对Web开发的集成特性,例如多方文件上传,利用Servlet listeners进行IOC容器初始化和针对Web的ApplicationContext。当与WebWork或Struts一起使用Spring时,这个包使Spring可与其他框架结合。

7.Spring Web MVC: Spring中的MVC封装包提供了Web应用的Model-View-Controller(MVC)实现。Spring的MVC框架并不是仅仅提供一种传统的实现,它提供了一种清晰的分离模型,在领域模型代码和Web Form之间。并且,还可以借助Spring框架的其他特性。

Servlet接口的方法有哪些?

A.doGet方法
B.doPost方法
C.init方法
D.forward方法
解析:

猜你喜欢

转载自blog.csdn.net/xiao__jia__jia/article/details/81169478