Spring知识简易理论

框架

	框架通俗的讲就是程序的架子,使用程序搭建出程序的基本架构,它的主要目的是针对一
	些通用的问题给出了便捷的解决方案,也可以是开发人员基于某一个框架快速的开发具体
	的相关应用。

常用的框架

     SSH
       Struts2
       Spring 
       Hibernate
     SSM
       SpringMVC
       Spring 
       Mybatis

Spring框架

     Spring是一个Service层的框架,它可以整合许多其他的框架进行工作,
     通俗的讲就是:Spring的理念是使现有技术更加实用,将一个大杂烩整合成现有的框架技术。

概念

	 Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器或者框架。

优点

	1.Spring是一个开源免费的框架。
	2.Spring是一个轻量级的框架,非侵入式的。
	3.控制反转IOC,面向切面AOP
	4.对事物以及框架都支持

Spring的配置文件

	  1.为eclipse配置spring的约束文件
	      Spring本身是基于xml配置来工作的,在使用Spring的过程中不可避免的要编写大量xml配置,
	      Spring官方提供了这些xml文件的编写规范,这是通过提供xml的约束文件来实现的。
	      DTD,通常文件的后缀 .dtd
	      Schema.通常文件的后缀为 .xsd
	      
	  所谓的xml的约束其实是一种限定xml文件写法的技术,主要分为两种
	     
	      1.Spring提供了Schema格式的约束,来限定Spring配置文件的写法。
	       (但是这个过程比较麻烦,通常我们会将约束文件交给开发工具管理)
	      2.将约束文件交给开发工具管理,开发工具可以通过解析约束文件了解xml的写法,
	         并在需要时为开发者提供标签提示
	      
	      
	  2.将spring的约束文件交给eclipse去管理
	    具体操作会有专门的博客

Spring的主要技术

	  IOC(DI)和 AOP
	  
	  IOC(DI) : 控制反转(依赖注入)
	
	  AOP : 面向切面编程

Spring IOC 控制反转

      控制反转:就是将对象的创建及生命周期管理的过程交给Spring来处理的过程。
       优点:在开发当中不在需要关注对象的创建以及对于对象生命周期的管理
            而是在需要的时候都由Spring框架来提供。

IOC 实现原理

	  在初始化一个Spring容器时,Spring会去解析指定的xml文件,
	  当解析到其中的<bean>标签时,
	  会根据该标签中的class属性指定的类的全名路径名,
	  通过反射创建该类的对象,并将该对象存入内置的Map中管理。

	  其中键就是该标签的id值也就是该对象。
	  之后,当通过getBean方法来从容器中获取对象时,其实就是根据掺
	  入的条件在内置的Map中寻找是否有匹配的键值,如果有则将该键值对中保存的对
	  象返回,如果没有匹配到则抛出异常。

IOC 获取对象的方式

   	  1.通过context.getBean()方式获取
        a.用id获取
        b.用class获取
        
        需要注意的是:
       	 通过class方式获取bean时,如果同一个类配置过多个bean,
       	 则在获取时因为无法确定到底要获取哪个bean会抛出异常,
       	 而id是唯一的,不存在这样的问题,所以建议大家尽量使用
       	 id获取bean

获取格式

<?xml version="1.O" encoding="UTF-8"?>
<beans xmIns="http://www.springframework.org/schema/beans"
	xmIns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http;/www.springframework.org/schema/beans/spring-beans-3.2.xsd ">
	
	<bean id="类名" class="类名在该包的路径"></bean>

    </beans>
    

别名标签

 	    在Spring中提供了别名标签<alias>可以为配置的<bean>起一个别名
 	    要注意的是这仅仅是对指定的<bean>起的一个额外的名字,并不会额外
 	    的创建对象存入map。
 
 	    格式
 	      <alias name = "要起别名的bean的id"alias=”要指定的别名“ />

Spring创建对象的方式

a.通过类的无参构造器创建

//当用最普通方式配置一个<bean>时,默认就是采用类的无参构造创建对象。在Spring容器初始化时,
//通过<bean>上配置class属性反射得到字节码对象,通过newInstance()创建对象
	Class c = Class.forName("类的全路径名称");
	Object obj = c.newInstance();

//这种方式下spring创建对象,要求类必须有无参的构造,否则无法通过反射创建对象,会抛出异常。
	public class Person{
  		public Person(String age){}
  		public void say(String age){
		
		 System.out.println("hello spring");
		}
	}

b.通过静态工厂创建对象

//很多的时候,我们面对的类是无法通过无参构造去创建的,例如该类没有无参构造,是一抽象类等等情况,
//此时无法要求spring通过无参构造创建对象,此时可以使用静态工厂方式创建对象。
	 
	 //类名为 calendar
	 public class CalendarStaticFacory{
 		public static Calendar getCalendar(){
 			return Calendar.getInstance();
		}
	}
	
	<bean id="calendar" class="com.biem.factory.CalendarStaticFactory" 
	    factory-method="getCalendar"></bean>

//spring创建对象的方式:通过静态工厂创建
	@Test
	public void test01(){
		ApplicationContext context 
                = new ClassPathXmlApplicationContext("applicationContext.xml");
		Calendar c1 = (Calendar)context.getBean("calendar");
		Calendar c2 = (Calendar)context.getBean("calendar");
	 	System.out.println(c1==c2);
}

c.通过实例工厂创建对象

//实例工厂也可以解决类中没有无参构造无法创建对象的问题,解决方法跟静态工厂类似,
//只不过实例工厂提供的方法不是静态的。
//spring需要先创建出实例工厂的对象,在调用实例工厂对象上指定的普通方法来创建对象
//所以实例工厂也需要配置到Spring中管理

	public class CalendarFactory{
		public Calendar getCalendar(){
 			return Calendar.getInstance();
		}
	}
<bean id="calendarFactory" class="com.biem.factory.CalendarFactory"></bean>
 <bean id="calendar" factory-bean="calendaryFactory" 
                                         factory-method="gatCalendar"></bean>

//spring创建对象的方式:通过实例工厂创建
	@Test
	public void test02(){
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Calendar c = (Calendar)context.getBean("calendar");
		System.out.println(c);
}

d.通过spring工厂创建对象

//Spring内置了工厂接口,也可以通过实现这个接口来开发Spring工厂,通过这个工厂创建对象。
	public class CalendarSpringFactory implements FactoryBean<Calendar>{
	//工厂生产的对象并返回
	@Override
	public Calendar getObject() throws Exception{
 	return Calendar.getInstance();	
	}

	//工厂生成对象的类型
	@Override
	public Class<?>getObjectType(){
		return Calendar.class;
	}
	//工厂生成的对象是否是单例
	//如果是true--是单例
	//如果是false--是多例
	@Override
	public boolean isStringleton(){
		return false;
		}
	}

<bean id="calendar" class="com.biem.factory.CalendarySpringFactory"></bean>

//spring 创建对象的方式:通过spring工厂创建
	@Test
	public void  test03(){
 		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
	    Calendar c1 = (Calendar)context.getBean("calendar");
 		Calendar c2 = (Calendar)coantext.getBean("calendar");
 		System.out.println(c1==c2);
 
}

单例和多例

 	 spring容器管理的bean在默认情况下,是单例的,
 	 也就是说:
 	 一个bean只创建一个对象,然后存到map当中,之后无论获得多
 	 少次该bean,都是同一个对象。
 	 
 	 spring默认采用的单例模式
 	 减少了对象的创建
 	 减少了内存的消耗。
 	 
 	 但是在实际的开发当中又存在多例需求的情况
 	 spring提供了选项
 	 可以将这个bean设置为多例模式

格式

<!--
  scope属性:控制当前bean创建的模式
  singleton:当前的bean处在单例模式当中,默认就是此模式
  prototype:当前的bean处在多例模式下
  -->
  <bean id="类名" class="类名的位置" scope="单例多例模式"

bean在单例模式下的生命周期

	 bean在单例模式下
	 1. spring容器启动时解析xml发现该bean标签后
	 2. 直接创建该bean的对象存入内部map中保存,此后无论调用多少次getBean()
	    获取该bean都是从map中获取该对象返回,一直是一个对象,
	 3. 此对象一直被Spring容器持有,直到容器退出时,随着容器的退出对象被销毁。

bean在多例模式下的生命周期

	 bean在多例模式下
	 1. spring容器启动解析xml发现该bean标签后,只是将bean进行管理。
	 2. 并不会创建对象,此后每次使用getBean()获取该bean时,spring都会重新创建该对象返回
	    每次都是一个新的对象,这个对象spring容器并不会持有,什么销毁取决于使用该对象的用
	    户自己什么时候销毁该对象。

懒加载机制

	 Spring默认会在容器初始化的过程中,解析xml,并将单例的bean创建并保存到map中,这样的机制
	 在bean比较少时问题不大,但一旦bean非常多时,spring 需要在启动的过程中花费大量的时间来创
	 建bean,花费大量的空间存储bean,但这些bean可能很久都用不上,这种在启动时在时间和空间上的
	 浪费显得非常的不值得,所以Spring提供了懒加载机制,所谓的暗恋你加载机制就是可以规定指定bean
	 不在启动时立即创建,而是在后续一用到时才创建,从而减轻了在启动过程对时间和内存的消耗。
		
	 (简单的理解就像电脑开机一样,当软件少的时候,开机启动并没有多大问题。但是当你软件多
	   了的时候,所有软件都加入开机启动,就会导致开机缓慢,而且大部分软件我们开机之后并不立
	   即使用,甚至很长时间都有可能不会使用,而懒加载就是解决这样的问题,将不常用的软件设置
	   为开机不启动,只是使用的时候才开启)
		
		注意:
			懒加载机制只对单例bean有作用,对于多例bean设置懒加载没有意义。

		方式一:未指定的bean设置懒汉模式


		方式二:全局加载懒汉模式

配置初始化和销毁的方法

	 在Spring中如果某个bean在初始化之后或销毁之前要做一些额外操作可以为该bean
	 配置初始化和销毁的方法,在这些方法中完成主要功能。

Spring中关键方法的执行顺序

     在Spring创建bean对象时:
     1.先创建对象(通过无参构造器或工厂)
     2.之后立即调用init方法来执行初始化操作
     3.之后此bean就可以拿来调用其他普通方法
     4.而在对象销毁之前spring容器调用其destory方法来执行销毁操作

Spring DI(依赖注入)

  在创建对象的过程当中,spring可以依据配置文件对这个对象的属性进行设置,
                                                  这个过程就是--依赖注入(DI)

注入方式

   1.通过set方式注入
   2.非spring内置的可以直接注入类型的注入
   3.基于构造方法的注入
   4.自动装配
    a.未指定的<bean>配置自动装配
    b.	全局配置自动装配

注解

概念

	 通俗的讲:如果说注释是给开发人员看的,那么注解就是给运行程序看的

背景

	在注解没有出现之前,xml 是各大框架的青睐者,
	他以松耦合的方式完成了框架中几乎所有的配置,
	但是随着项目越来越庞大,xml 的内容也越来越复杂,相对维护成本变高。
	
	于是就有人提出来一种标记式高耦合的配置方式 - - >注解 
	方法上可以进行注解,
	类上也可以注解,
	字段属性上也可以注解
	反正几乎需要配置的地方都可以进行注解,
	
	关于注解 和xml 两种不同的配置模式,争论了好多年了,各有各的优劣,
	注解可以提供更大的便携性易于维护,但耦合度高,而xml 相对于注解则是相反的,
	
	一个注解准确意义上来说,只不过是一种特殊的注释而已,
	如果没有解析它的代码,它可能连注释都不如,
	在Java技术里注解的典型应用就是可以通过
	反射技术得到类里面的注解,以决定怎么去运行一个类。		 

定义注解

	1.定义注解@Annotation
 public @inerface MyAnnotation{
 }
 
	2.把注解应用到指定的地方(属性,方法,类,参数,包等)
	1)应用注解
	@MyAnnotation
	  public class AnnotationTest{
	  @MyAnnotation
	  public void method(){}
      public void method(@MyAnnotation int i){}
     }
     
	3.使用反射技术解析注解

原生注解,用于修饰注解的注解

  	1.@Target(ElementType.xxx):指定这个注解的使用的位置(类,方法,属性,参数,包等)
	     @Target(ElementType.METHOD)-->方法
	     @Target(ElementType.TYPE)-->注解类,接口(包括注释类型)声明或者枚举的声明
	     @Target(ElementType.CONSTRUCTOR)-->构造方法声明
	     @Target(ElemenType.FIELD)-->字段声明(包括枚举变量)
	     @Target(ElementType.LOCAL_VARIABLE)-->局部变量声明
	     @Target(ElementType.PACKAGE)-->包声明
	     @Target(ElemenatType.PARAMETER)-->参数声明
	     
	2.@Retention(RetentionPolicy.SOURCE)被它修饰的注解保留域
	   编译器-->类加载器-->JVM.java-->.class-->加载-->运行
	   SOURCE:源码级别,给编译器看的,编译完之后直接丢弃该种策略的注解,生成的.class文件中没有改类型的注解
	   CLASS:给类加载器看的,在类加载时加载时可以做一系列引导和操作,编译器编译后存在,类加载器加载完之后,丢弃该保留域的注解
	   RUNTIME:给JVM看的,在程序运行的过程中做相关的操作。编译器编译后保留,类加载其加载之后保留,在JVM运行时通过反射技术反射使用的是什么注解,注解属性值是什么,根据他们两个值做i对应的操作,
   
    3.@Documented:自定义注解如果使用Documented,生成的doc文档上,使用该自定义注解的地方会显示注解信息。
	   注解中的属性:
	   a.注解定义属性和接口定义方法类似,缺省默认是public
	   public 类型 属性名称();
	   b.定义属性时,如果没有使用default指定默认值,使用当前注解必须为该属性赋值
	   使用default指定默认值之后,该属性在注解时可以赋值,也可以不赋值
	   c.注解中的属性类型是有要求的,可以是八种基本数据类型,也可以是枚举类型,Class类型,string类型等以及以上类型的一维数组
	   如:String[] names default{}'
	   注意:在使用注解时,如果数组类型的属性的值是一个值的话,赋值时可以把{}省略掉
	   d。存在一个特殊的属性:value。如果只为该属性赋值,value是可以省略掉的。
	   但是如果为注解中多个属性同时赋值的话,value=不可以省略

    4.如何使用注解
	   @注解的名称 (属性名=属性值)
	   @注解的名称(属性名1=属性值1,属性2=属性值2...)
	   
    5.如何反射注解
	   @Retention(RetentionPolicy.RUNTIME)
	   要想注解被反射,注解的保留域必须设置RUMTIME保留域
	   JDK中提供了AnnotationElement接口,该接口提供了反射注解的几个方法;
	   1)getAnnotation() 如果元素该元素指定类型的注解,则返回,否则返回null
	   2)getAnnotations();返回此元素上存在的所有的注解
	   3)getDeclaredAnnotations();返回直接存在此元素上的所有注解
	   4)boolean isAnnotationPresent:判断该元素上是否存在指定的注解,存在返回true 不存在返回false
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值