文章目录
- 1. Aop 面向切面
- 2. IOC
- 3. 什么是springBeans?
- 4. spring bean的几种作用域
- 5. spring框架中的单利不是线程安全的。
- 6. bean的生命周期
- 7. 什么是spring的内部bean?
- 8. spring如何注入一个集合?
- 9. 什么是bean装配?
- 10. 什么是bean自动装配?
- 10. spring可以注入null和空字符串
- 11. spring的注解装配方式默认是不开启的。需要在spring配置文件中配置元素
- 12. spring支持的ORM:
- 13. spring支持的事务管理:
- 14. spring框架的有点有哪些?
- 15. spring模块有哪些?
- 16. 关于spring的事务,即操作数据库的事务。
- 17. BeanFactory 和ApplicationContext的区别。
- 18. ApplicationContext的实现方式有几种?
- 19. spring配置应用到开发者的3中方式?
- 20. 对常见的注解@Required @Autowire @Qualifier的解释。
- 21. spring中用到了哪些设计模式?
- 22. springMVC的优点
- 23. springmvc的工作流程
- 24. Springmvc的控制器是不是单例模式,如果是怎么解决线程安全问题
- 25,springMVC与struct2的区别。
- 26,@Controller 是控制器注解
- 27. @RequestingMapping 是用来处理请求地址的注解,如果是作用在类上是所有方法的父地址
- 28 如果在拦截请求中,怎么拦截get方式提交的方法?
- 29 怎么在方法里面得到Request或session?
- 30 springmvc的返回值是什么?
- 31 怎么设定重定向和转发?
- 32 springmvc 用什么对象从后台向前台传递数据?
- 33 当控制器向AJAX返回特殊对象,如list,需要做什么处理?
- 34 spring事务传播机制,7种事务传播机制
- 35 spring容器管理的对象什么时候销毁
- 36 spring容器用的是单利还是多例?
- 37 spring哪些类需要注入,哪些类需要new
1. Aop 面向切面
是spring的一种编程思想。目的是把业务逻辑和系统逻辑区分开。我们专注的是业务逻辑,而系统逻辑不是我们关注的点,这就可以借助于Aop帮助我们完成。还是以保存数据库为例:我们关注的是增删改查,以查为例,我们关注的代码是用哪个字段去查,然而,操作数据库我们必须要先开启数据库,加载数据库驱动,完了还要关闭数据库,搞不好还要回滚。很繁琐,一急还容易给忘了,这些就属于系统逻辑。所以Aop就出现了,帮助我们开启关闭。我们关注与业务逻辑"查"就行了。
Aop需要的工具包是aspectj。常见的术语有分两类,一是:切点(apointcut),切面(aspect)。切点是哪个类或哪个方法需要加前后操作;切面是前后操作的内容。二是:前置通知(before),后置通知(after),环绕通知(around),异常通知(after-throwing)。前置通知是在切点执行前自动执行。后置通知就是在切点内容执行自动后执行。环绕通知就厉害了可以控制切点方法的执行。异常通知就是可以获取切点抛出的异常。
最后,对于AOP的使用,目前我见过和使用过得分两类,一个是加在配置文件中,一个通过注解是直接加在切点方法上。前者比较隐秘,但没有动源代码,没看该配置文件的人都不知道用了aop。后者比较明了,看到源码就知道这里加了aop,但动了源码。
2. IOC
就是控制反转,也可以说成依赖注入,两种说法是一个东西。它也是一种编程思想。即有A,B两个类,其中B类是A的一个属性,所以也可以说成A类依赖B类。传统的建类的方式是同时new连个类,然后把B赋值到A中。这种耦合性比较高,如果有类似B的类也要加入到A中,就要修改A类了。而控制反转是借助于接口创建依赖的类,即精简了代码,也提高了扩展性。就像下面的例子。
class A{
private B b;
public B getB() {
return this.b;
}
public void setB(B b) {
this.b = b;
}
}
interface B{
}
class B1 implements B{
}
class B2 implements B{
}
@Test
public void TestDI(){
A a=new A();
System.out.println(a.getB());//null
a.setB(new B1());
System.out.println(a.getB());//test.B1@5b37e0d2
a.setB(new B2());
System.out.println(a.getB());//test.B2@4459eb14
}
再者,要介绍的是依赖注入的两种方式,上面按个是属于setter方式注入,还有一种是构造器注入,即把依赖的类放入到构造函数参数中,当创建A类时会强制提醒创建依赖的对象。案例如下:
class A1{
public B b;
public A1(B b) {
this.b = b;
}
}
interface B{
}
class B1 implements B{
}
class B2 implements B{
}
@Test
public void TestDI2(){
A1 a1=new A1(new B1());
System.out.println(a1.b);//test.B1@5b37e0d2
}
这里A 就相当于一个容器,把想要的实例放在A中创建即可。
最后,要介绍的就是SpringIOC容器了(就是A的角色)。这是一个负责管理创建,管理,装配,配置对象的容器。创建A类只需要getBean这个类即可,至于A类的依赖类由spring容器负责自动创建,很方便。springIOC的实现常见的也有两种方式,一种是在xml文件中配置。如下:
<beans>
<bean id ="B1" class ="test.B1">
</bean>
<bean id="A" class="test.A">
<property name="B">
<ref bean="B1"/>
</property>
</bean>
</beans>
这类方式的源码很复杂,主要是解析上面的xml文件和通过反射的方式递归创建依赖类。
另外一种是通过注解方式,形如:
@Service("A")
class A{
@Autowired
public B1 b1;
}
@Service("B1")
class B1{
}
两种方式使用的时候都是通过ApplicationContext.getBean(“A”)的方式创建A类的。
总结:IOC是一种让依赖的类自动注入创建的编程思想,对象给出他们的依赖,而不是自己创建和查找。它降低了代码耦合,增强了扩展性。可以通过构造器注入和setter注入。在springIoc容器中,让spring容器负责创建管理对象,可以通过在xml文件配置依赖类或者通过注解注入依赖类。最后通过getBean的方式加载类。
3. 什么是springBeans?
Beans就是通常配置在applicationContext.xml文件中的Beans节点了。他们构成了spring应用的主干类。这些bean被springIOC容器加载,这些bean默认都是单利的,可以通过设置prototypebean="false"做修改。
4. spring bean的几种作用域
singleton:即单利,一个springIOC只有一个实例
prototype:一个springIOC可以有多个实例
request:每个http请求 都会创建一个bena,该作用域仅在web的springApplicationContext情形下有效。
session:在一个httpSession中,一个bean对应一个实例,该作用域仅在web的springApplicationContext情形下有效。
global-session:在一个全局HTTPsession中,一个bean对应一个实例,该作用域仅在web的springApplicationContext情形下有效。
5. spring框架中的单利不是线程安全的。
6. bean的生命周期
先上个关于spring加载bean的代码
public class Hello Implements BeanNameAware,BeanFactoryAware,BeanPostProcessor,DisposableBean{
@Override
public void setBeanName(String arg0){
System.out.println("haha "+arg0);//注意 这个arg0参数是来自配置文件中bean的id
}
public void init(){//这个是配置文件bean要执行的init方法
System.out.println("laiba");
}
@Override
public void setBeanFactory(BeanFactory arg0)throws BeansException{
System.out.println("haiyoushui");
}
@Override
public Object postProcessAfterInitialization(Object arg0,String arg1)throws BeansException{
System.out.println("postafter"+arg1);
return arg0;//这个要返回object,否则不能执行出postProcessBeforeInitialization方法内容。
}
@Override
public Object postProcessBeforeInitialization(Object arg0,String arg1)throws BeansException{
System.out.println("postbefore");
}
@Override
public void destroy()throws Exception{
System.out.println("end...");
}
}
public class SpringTest{
public static void main(Stringp[] args){
ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml");
Hello hello=(Hello)context.getBean("hello");
}
}
applicationContext.xml配置文件中的bean配置:
<bean id ="hello" class="test.Hello" init-methond="init" destroy-method="destroy"/>
输出:
haha hello
haiyoushui
laiba
postbefore
postaftercfx
从结果中可以看出,先执行setBeanName()方法,这个方法是来自BeanNameAware接口的实现。然后执行setBeanFactory方法,它是来自BeanFactoryAware接口的实现。然后是init方法,这是配置在bean中的方法。最后分别是:postProcessBeforeInitialization和postProcessAfterInitialization方法,这是来自BeanPostProcessor接口的实现。
所以spring的生命周期总结如下:
1,首先spring容器从xml文件中读取bean的定义,并实例化,
2, spring根据bean的定义填充实例的所有属性。
3,如果bean实现了BeanNameAware接口,spring会传递bean的id给setBeanName.
4,如果bean实现了BeanFactoryAware接口,spring传递beanFactory给setBeanFactory方法
5,执行bean的init-method方法
6,接着是实现与bean相关联的前后置通知BeanPostProcessor,调用相应的before和after方法
7,正式使用该实例
8,如果bean实现了DisposableBean,它将调用destory方法。
总结上面的过程跟网上流行的稍微不同,一是,init-method是在前后置通知间进行的,但我测试的结果是在其前就已经执行了。二是,实例在正式使用前会检测一列的接口实现,上面并不完整。最后是我这里测试的destroy方法没用执行,不知道原因。姑且与网上的流行说法为准吧。
最后,面试的简而言之:创建bean实例,加载bean的属性和依赖,将bean实例传给后置处理器,调用init方法,使用bean,容器关闭时,调用bean的destroy方法销毁实例。
7. 什么是spring的内部bean?
就是一个bean仅被用作另一个bean的属性使用时,就是一个内部bean,即innerBean。这种bean通常匿名使用,并且其作用域是多例的。
8. spring如何注入一个集合?
spring提供了list(允许相同的值),set(不允许相同的值),hash(键值对),props(也是键值对,但键值都只能是string)这四种集合。
9. 什么是bean装配?
把spring容器中的bean组装到一起,并装载其依赖的bean
10. 什么是bean自动装配?
spring容器能够自动装配相互合作的bean。这个比较便利,不用再xml文件一个个配置各个bean的依赖,很简洁,是大部分项目的使用方式。配置形式如下:
<bean id="customer" class="test.Hello" autowire="byName"/>
10. spring可以注入null和空字符串
11. spring的注解装配方式默认是不开启的。需要在spring配置文件中配置<context:annotation-config />元素
12. spring支持的ORM:
hibernate iBatis JPA TopLink JDO ojb
13. spring支持的事务管理:
1,编程式事务管理 ;2,声明式事务管理。前者灵活,程序员自己写每个增删改查。后者通过注解或xml配置替程序员写事务管理部分,使之更关注与业务逻辑,也就是使用了aop。如使用mybatis,就是只用在xml中写好sql,并在xml声明。
举例:
在web-inf目录下创建个管理spring ORM的xml,加入以下:
<!--spring声明式事务的配置-->
<tx:advice id="txAdvice" transcation-manager="transcationManager">
<tx:attributes>
<!--给每种事务方式设置spring事务传播机制-->
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="find*" propagation="SUPPORTS"/>
<tx:method name="select*" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<!-- 对于上面声明的事务所在的方法使用aop进行管理,也就是满足上以上面哪些save,update等开头的方法才会使用事务-->
<aop:config expose-proxy="true">
<aop:pointcut expression="execution(* com.mybatis.service.impl.*.*(..))" id="txPointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
如果在com.mybatis.service.impl包下有个类是:
public Student findone(String name){
...
}
那这个查询方法就会使用事务管理。而不用像编程式事务要把rollback写在代码中。
14. spring框架的有点有哪些?
轻量,spring基本版本大约2M;
控制反转,spring通过控制反转实现了解耦合;
面向切面编程
容器,springIOC容器可用来配置和管理对象实例;
MVC框架,是spring精心设计的框架,可很好的替代传统web框架;
15. spring模块有哪些?
coremodule,beanmodule,contextmodule,ormmodule,jdbcmodule,webmodule.
16. 关于spring的事务,即操作数据库的事务。
17. BeanFactory 和ApplicationContext的区别。
首先BeanFactory是bean集合的工厂,可用来创建bean实例,并管理bean的生命周期,调用初始化方法,根据请求分发bean功能。当然ApplicationContext也可以做到这些,可以说后者比前者的作用范围更广些。在次基础上ApplicationContext提供了统一的资源文件读取方式,支持国际化的文本消息。
18. ApplicationContext的实现方式有几种?
1,从classpath的xml配置中读取上下文配置。
ApplicationContext context=new ClassPathXmlApplication(“bean.xml”);
2,从本地文件系统中读取xml上下文配置。
Application context=new FileSystemXmlApplication(“bean.xml”);
3,由web应用的xml文件读取上下文,即在web.xml中配置上下文配置文件地址,有web容器读取。
4,AnnotationConfigApplicationContext(基于java配置启动容器)
19. spring配置应用到开发者的3中方式?
1,基于xml配置
就是常见的web.xml,applicationContext.xml的配置方式。可以配置spring支持的一系列如context,orm,beans,jdbc,app,mvc,aso等的标签
2,注解配置
注解装配在spring默认是关闭的。
在配置中加如下配置就可以使用注解装配模式了。然后使用@Required @Autowire等注解在实例中装配相应的属性,构造方法,变量等。
<beans>
<context:annotation-config />
</beans>
3,java配置
是由@Configuration注解和@Bean注解来实现的,最后由AnnotationConfigApplicationContext类进行实例化。
明显这个@Configuration作用类似ApplicationContext.xml配置文件,@Bean就是其中的实体了。
案例如下:
@Configuration
public class AppConfig{
@Bean
public MyService myService(){
return new MyServiceImpl();
}
public static void main(String[] args){
ApplicationContext ctx=new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService=ctx.getBean(MyService.class);
myService.doStuff();
}
20. 对常见的注解@Required @Autowire @Qualifier的解释。
1, @Required
如果实体的一个属性在配置文件中没有配置,但是在实体中给该属性加了@Required注解,这是就会报异常。可见@Reuqired注解的作用是检查该属性是不是被正确设置。
案例如下:
配置文件:
<context:annotation-config />
<bean id="resultMessage" class="test.resultMessage">
<property name="code" value="001" />
</bean>
public class ResultMessage{
private String code;
private String message;
public String getCode(){
return code;
}
@Required
public void setCode(String code){
this.code=code;
}
public String getMessage(){
return message;
}
@Required
public void setMessage(String message){
this.message=message;
}
public class SpringTest{
public static void main(Stringp[] args){
ApplicationContext context =new ClassPathXmlApplicationContext("applicationContext.xml");
ResultMessage resultMessage=(ResultMessage)context.getBean("resultMessage");
}
}
2, @Autowire
这个没啥讲解的,是用来自动装配bean的关联依赖属性的。相当于配置文件中的property作用。
3,@Qualifier
根据bean的id装配指定的bean配置,比如一个类同时设置了两个属性值,那么取哪个呢?这是就根据@Qualifier(“beanId”),获取指定的配置。案例:
public class Customer{
@Autowire
private Person person;
}
配置文件:
<bean id="customer" class="test.customer"/>
<bean id="personA" class="test.Person">
<property name="name" value="first"/>
</bean>
<bean id="personB" class="test.Person">
<property name="name" value="second"/>
</bean>
问题:上面配置中有个两个person,如果使用自动装配,那么会装载personA 还是personB呢?
这是就用到了@Qualifier
public calss Customer{
@Autowired
@Qualifier("personA")
private Person person;
}
21. spring中用到了哪些设计模式?
单例,代理,工厂(beanFactory),模板.
22. springMVC的优点
1,是spring的一个模块,可以与java的其他模块紧密结合
2,是基于组件的,无论是控制器还是视图都是java组件
3,支持各种是视图技术,不单单是jsp
4,支持各种资源请求的映射策略
5,易于扩展
23. springmvc的工作流程
1,用户发送请求到dispatcherServlet(中央处理器)
2,dispatcherServlet查询handleMapping,经handlerAdapter适配器找到处理请求的controller
3,controller分发到service做逻辑处理,返回modelAndView
4,dispatcherServlet,将modelAndView传给ViewReslover视图解析器,返回具体的view实体
5,dispatcherServlet做相应渲染后,返回给用户。
24. Springmvc的控制器是不是单例模式,如果是怎么解决线程安全问题
是单例,且不是线程安全的,因为如果加锁成同步的,会影响性能。解决方案是不要在controller层做逻辑处理,只把他当做一个分发器,转到service层处理。我觉着这就是为什么都建议不建议在controller做逻辑处理的根本原因吧!
至于controller为什么不是多例,我认为应该是前端用户点击的次数很多,而且很多点击只是做简单的转发,不涉及业务处理,那么没必要每次点击都new个控制器,很浪费堆内存,而且响应慢。再者业务逻辑都放置了service,这是是多利的,线程安全的。
25,springMVC与struct2的区别。
struct2是很遥远的框架了。
1,springMVC的入口时servlet前端控制器,struct2是filter过滤器。
2,springmvc是基于方法开发的,一个url对应一个方法,控制器是单利的,struct2是基于类开发的,参数是类的属性,只能设计成多利。
26,@Controller 是控制器注解
27. @RequestingMapping 是用来处理请求地址的注解,如果是作用在类上是所有方法的父地址
28 如果在拦截请求中,怎么拦截get方式提交的方法?
在@RequestingMapping 注解中加上method=RequestMothod.GET
29 怎么在方法里面得到Request或session?
直接在方法的形参中声明request,Springmvc就自动把request对象传入。同样的获取前台参数也是在方法形参中声明,但参数名要保持一致
30 springmvc的返回值是什么?
有很多种,可以使string,modelAndView
返回string会比较好。
31 怎么设定重定向和转发?
重定向,在返回值前加forward:形如forwar:user.do?name=method1"
转发,在返回值前加redirect 形如 redirect:http://www.baidu.com
32 springmvc 用什么对象从后台向前台传递数据?
通过modelMap对象,可以在这个对象里面用put方法把对象加到里面,然后前台就可通过el表达式拿到。
33 当控制器向AJAX返回特殊对象,如list,需要做什么处理?
加上@ResponseBody注解
34 spring事务传播机制,7种事务传播机制
spring事务也就是数据库的事务。复杂的sql有子查询等,转成spring中就是一个方法(父方法)调用另一个方法(子方法),两个方法中都有对数据库的操作,那么事务在多个方法中是如何传播的。
考虑两个问题:1,子方法的事务是用父方法的事务还是自己重新连接数据。2,如果把两个方法看为一体,父方法回滚字方法会不会也回滚?
传播机制:
1,REQUIRED (也是默认的事务方式)
使用:@Transactional(propagation=Propagaion.REQUIRED),还有一种方式是在xml中配置,在13. spring支持的事务管理中有介绍到。
定义:如果父方法有事务就加入,没有就创建一个。
比如说A(){inert()}方法调B(){delete()}方法,是个先插入后删除的过程。那么执行delete时就不用再去连接数据库了(如jdbc),最后两个一起commit。
2.NOT_SUPPORTED
定义:spring不为当前方法开启事务。
也就是直接插入删除,失败的话也不能回滚。
3,REQUIRES_NEW
不管是否存在事务,都创建一个新的事务。同时父方法中的事务不能提交,要等子方法执行完了再提交。父子方法各自commit提交一次,字事务先提交。
4,MANDATORY
必须在一个已有的事务中执行,否则报错。
也及时B方法执行delete是发现A没有事先开事务就报错。
5,NEVER
必须在一个没有的事务中执行。否则报错
也就是父方法不能开启事务
6,SUPPORTS
如果其他
35 spring容器管理的对象什么时候销毁
1,如果是单利的对象,启动的时候会调用构造方法创建对象,容器关闭的时候调用销毁方法。
2,如果是多利的对象,每次调用的时候用构造方法创建对象,容器不会管理这个bean,也不会销毁,通过垃圾回收机制回收。
36 spring容器用的是单利还是多例?
这种问题不能一概而论,有单利也有多例,默认是单例,对于多例,可以创建多个实例,可以创建中间对象做更多灵活性处理。
37 spring哪些类需要注入,哪些类需要new
这个不太好说,看网上的说的,感觉挺有道理的,说是需要直接new的通常是数据对象。需要注入的通常是跨层调用的类。
再者就是我们在springmvc的controller控制层会使用@Autowire注入service层接口,在service层注入dao层接口。使用的时候我们直接通过注入的变量就可以调用方法了,并没有new实现该接口的实现类。这里的三层就是跨层调用,对应的类也需要我们注入。
还有就是我也会使用spring容器帮我创建大对象,比如对象里面的层级很多,在做单元测试的时候,不得不先new里面的对象,再把对象赋值给外面的大对象。否则直接用new最外层的大对象就会报空指针。这时候可以使用spring容器getbean的方式加载,不过要在创建类的时候给每个类加上@Service注解。