欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring面试题目自我解答

程序员文章站 2022-05-29 09:37:25
...
  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());//[email protected]
		a.setB(new B2());
		System.out.println(a.getB());//[email protected]
	}

再者,要介绍的是依赖注入的两种方式,上面按个是属于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);//[email protected]
	}

最后,要介绍的就是SpringIOC容器了。这是一个负责管理创建,管理,装配,配置对象的容器。创建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的方式加载类。

  1. 什么是springBeans?
    Beans就是通常配置在applicationContext.xml文件中的Beans节点了。他们构成了spring应用的主干类。这些bean被springIOC容器加载,这些bean默认都是单利的,可以通过设置prototypebean="false"做修改。
  2. spring bean的几种作用域
    singleton:即单利,一个springIOC只有一个实例
    prototype:一个springIOC可以有多个实例
    request:每个http请求 都会创建一个bena,该作用域仅在web的springApplicationContext情形下有效。
    session:在一个httpSession中,一个bean对应一个实例,该作用域仅在web的springApplicationContext情形下有效。
    global-session:在一个全局HTTPsession中,一个bean对应一个实例,该作用域仅在web的springApplicationContext情形下有效。
  3. spring框架中的单利不是线程安全的。
  4. 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(".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方法没用执行,不知道原因。姑且与网上的流行说法为准吧。

  1. 什么是spring的内部bean?
    就是一个bean仅被用作另一个bean的属性使用时,就是一个内部bean,即innerBean。这种bean通常匿名使用,并且其作用域是多例的。
  2. spring如何注入一个集合?
    spring提供了list(允许相同的值),set(不允许相同的值),hash(键值对),props(也是键值对,但键值都只能是string)这四种集合。
  3. 什么是bean装配?
    把spring容器中的bean组装到一起,并装载其依赖的bean
  4. 什么是bean自动装配?
    spring容器能够自动装配相互合作的bean。这个比较遍历,不用再xml文件一个个配置各个bean的依赖,很简洁,是大部分项目的使用方式。配置形式如下:
<bean id="customer" class="test.Hello" autowire="byName"/>
  1. spring可以注入null和空字符串
  2. spring的注解装配方式默认是不开启的。需要在spring配置文件中配置<context:annotation-config />元素
  3. spring支持的ORM:
    hibernate iBatis JPA TopLink JDO ojb
  4. spring支持的事务管理:
    1,编程式事务管理 ;2,声明式事务管理。前者灵活,程序员自己写每个增删改查。后者通过注解或xml配置替程序员写事务管理部分,使之更关注与业务逻辑,也就是使用了aop
相关标签: 2020