Spring学习笔记

Spring学习笔记

1、Spring的组成架构:

 

Core和Beans模块中,BeanFactory是一个工厂模式的实现。

Context模块中,ApplicationContext接口是该模块的焦点。

Data Access/Intergration层:

OXM模块为JAXB、Castor、XMLBeans等提供一个支持Object/XML映射的接口。

JMS模块提供关于消息的生产和消费相关的技术。

 

2、Spring XML文件的配置:

<beans>

       <bean id=”” class=”全类名”>

              <property name=”” value=””></property>

       </bean>

</beans>

配置bean时候,class:bean的全类名,通过反射的方式在IOC容器中创建Bean,所以要求Bean中必须有无参的构造器。

id:标识容器中的bean,值唯一。

//创建Spring的IOC容器对象即实例化,其中ClassPathXmlApplicationContext是ApplicationContext接口的实现类,该实现类从类路径加载配置文件

ApplicationContext ctx =new ClassPathXmlApplicationContext(“configName.xml”);

//获取bean的实例

ctx.getBean(“id值”);

ApplicationContext是BeanFactory的子接口,代表IOC容器。在SpringIOC容器读取Bean配置创建Bean实例之前,必须对它进行实例化,只有在容器实例化后,才可从IOC容器中获取Bean实例并使用。

3、依赖注入方式:属性注入、构造器注入

(1)属性注入:即通过setter方法注入Bean的属性值或依赖的对象,属性注入使用<property>元素,使用name属性指定Bean的属性名称,value属性或者<value>子节点指定属性值

属性注入是实际应用中最为常见的注入方式

<beans>

       <bean id=”” class=”全类名”>

              <property name=”userName” value=”wuRong”></property>

       </bean>

</beans>

(2)构造方法注入:通过构造方法注入Bean的属性值或者依赖的对象,它保证了Bean实例在实例化后就可以使用。

构造器注入在<constructor-arg>元素里声明属性,<constructor-arg>中没有name属性。

<bean id=”” class=””>

<constructor-arg value=”属性1”></constructor-arg>

<constructor-arg value=”属性2”></constructor-arg>

<constructor-arg value=”属性n”></constructor-arg>

</bean>

当一个类需要引用另一个类的时候,xml文件中的bean配置方法如下:

<beans>

       <bean id=”” class=”全类名”>

<property  name=”” value=””></property>

<property  name=”引用类对象名” ref=”引用类的beanId”></property>

       </bean>

</beans>

属性需要先初始化,然后才可以级联属性赋值,否则会有异常。

集合属性的配置:<list> <set> <map>

<list>集合配置方式:

<bean id=”” class=””>

       <property  name=”” value=””></property>

<property  name=”listName” >

       <list>

              <ref  bean=”元素1”/>

              <ref  bean=”元素2”/>

              <ref  bean=”元素3”/>

</list>

</property>

</bean>

<map>集合配置方式:

<bean id=”” class=””>

       <property  name=”” value=””></property>

<property  name=”mapName” >

       <map>

              <entry  key=”” value-ref=””></entry>

              <entry  key=”” value-ref=””></entry>    //键值对

</map>

</property>

</bean>

配置properties属性值:使用props和prop子节点为属性赋值

<bean id=”” class=””>

<property  name=”properties” >

       <props>

<prop  key=”user” >root</prop>

<prop  key=”password” >123456</prop>

<prop  key=”driverClass” >com.mysql.jdbc.Driver</prop>

</ props>

</property>

</bean>

还可以通过p命名空间,为bean的属性赋值,需要先导入p命名空间。

<bean id=”person” class=”com.spring.Person” p:age=”” p:name=””></bean>

其中Person是一个类,age和name是Person类中的成员属性,这种方式更加简洁。

4、自动装配:XML配置里的Bean自动装配,SpringIOC容器可以自动装配Bean,需要做的仅仅是在<bean>的autowire属性里指定自动装配的模式。

byType: 根据类型自动装配,若IOC容器中有多个与目标Bean类型一致的Bean,在这种情况下,Spring将无法判断哪个Bean最合适该属性,所以不能执行自动装配。

byName:根据名称自动装配,必须将目标Bean的名称和属性名设置的完全相同。根据bean的名字和当前bean的setter风格的属性名进行自动装配。若有匹配的,则进行自动匹配,若没有匹配的则不装配。

Constructor:通过构造器自动装配,当Bean中存在多个构造函数时候,此种自动装配方式将会很复杂,不推荐使用。

5、Bean配置的继承:使用bean的parent,被继承的bean称为父bean,继承这个父类的bean被称为子bean;

子bean从父bean中继承配置,包括bean的属性配置;

子bean也可以覆盖从父bean继承过来的配置;

父bean可以作为配置模板,也可以作为bean实例。若只想把父bean作为模板,可以设置<bean>的abstract属性为true,这样Spring将不会实例化这个Bean。

6、依赖Bean配置:Spring允许通过depend-on属性设定Bean前置依赖的bean,前置依赖的bean会在本bean实例化之前创建好;

如果前置依赖于多个bean,则可以通过逗号,空格的方式前置bean的名称。

7、bean的作用域:prototype原型,每次创建bean都会返回一个新的bean实例。

singleton单例,默认的作用域,容器初始化化时就已经创建了bean实例,在整个容器的生命周期中都只有这一个实例。

Bean的作用域有5种:singleton、prototype、request、session和global session。如果一个Bean的作用域为singleton,那么Spring IoC容器就只会存在一个共享的Bean实例,并且所有对Bean的请求,只要id与该Bean匹配,就只会返回Bean的同一个实例。换言之,当一个Bean定义设置为singleton作用域时,Spring IoC只会创建该Bean定义的唯一实例。这个单一实例会被存储在单例缓存中,并且所有针对该Bean的后续请求和引用都将返回被缓存的对象实例。

Prototype作用域的Bean会导致在每次对该Bean请求(将其注入到另一个Bean中,或者以程序调用的方式调用容器的getBean()方法)时,都会创建一个新的Bean实例。根据经验,对有状态的Bean使用prototype作用域,对无状态的Bean使用singleton作用域。

8、导入外部属性文件:

<context:property-placeholder location=”classpath:db.properties”/>

//使用外部化属性文件的属性

<property name=”user” value=”${user}”></property>

<property name=”password” value=”${ password }”></property>

其中db.properties为外部属性配置文件名称,user和password都是该文件中配置的属性名。

9、Spring表达式语言:SpEL,它是一个支持运行时查询和操作对象图的强大的表达式语言;

语法类似于EL:SpEL使用#{}作为定界符,所有在大框号中的字符都被认为是SpEL;

SpEL为bean的属性进行动态赋值提供了便利。

通过SpEL可以实现一下功能:

----通过bean的id对bean进行引用;

----调用方法以及引用对象中的属性;

----计算表达式的值;

----正则表达式的匹配。

//引用其他对象:

<property name=”prefix” value=”#{prefixGenerator}”></property>

//引用其他对象的属性

<property name=”suffix” value=”#{sequenceGenerator.suffix}”></property>

//调用其他方法

<property name=”prefix” value=”#{prefixGenerator.toString()}”></property>

//方法的连接操作

<property name=”prefix” value=”#{prefixGenerator.toString().toUpperCase()}”></property>

10、IOC容器中Bean的生命周期方法:

SpringIOC容器对Bean的生命周期进行管理的过程如下:

---通过构造器或工厂方法创建bean实例;

---为bean的属性设置值和对其他bean的引用;

---调用bean的初始化方法;

---bean可以使用了;

---当容器关闭时,调用bean的销毁方法。

在bean的申明里设置init-method和destory-method属性,为bean指定初始化和销毁方法。

<bean id=”car” class=”com.spring.bean.Car” init-method=”初始化方法名” destroy-method=”销毁方法名>

       <property name=”” value=””></property>

</bean>

类Car中定义了初始化方法init()和销毁方法destory(),方法名叫什么无所谓,但是一定要和bean配置文件中名字一样。

11、Bean后置处理器:它允许在调用初始化方法前后对Bean进行额外的处理。

对Bean后置处理器而已,需要实现Inerface BeanPostProcessor接口,在初始化方法被调用前后,Spring将把每个Bean实例分别传递给上述接口的下面两个方法:

postProcessAfterInitialization(Object bean,String beanName)

postProcessBeforeInitialization(Object bean,String beanName)

添加Bean的后置处理器后Bean的生命周期:SpringIOC容器对Bean的生命周期进行管理的过程:

---通过构造器或工厂方法创建bean实例;

---为bean的属性设置值和对其他bean的引用;

---Bean实例传递给Bean后置处理器的postProcessBeforeInitialization()方法;

---调用bean的初始化方法;

---Bean实例传递给Bean后置处理器的postProcessAfterInitialization()方法;

---bean可以使用了;

---当容器关闭时,调用bean的销毁方法。

12、基于注解的bean配置方式(基于注解配置bean,基于注解来装配Bean的属性)

在classpath中扫描组件:组件扫描,Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件。特定组件包括:

--- @Component:基本注解,标识一个受Spring管理的组件

--- @Responsitory:标识持久层组件

--- @Service:标识服务层(业务层)组件

--- @Controller:组件表现层组件

对于扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写。也可以在注解中通过value属性值标识组件的名称。

当在组件类上使用了特定的注解之后,还需要在Spring的配置文件中申明<context:component-scan>:

--- base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及子包中所有的类;

--- 当需要扫描多个包时,可以使用逗号隔开。

--- 如果仅仅希望扫描特定的类而非基包下的所有类,可使用resource-pattern属性过滤特定的类,示例:

<context:component-scan

       base-package=”com.zte.spring.beans”

       resource-pattern=”autowire/*.class”>

</ context:component-scan>

--- <context:include-filter>子节点表示要包含的目标类

--- <context:exclude-filter>子节点表示要排除在外的目标类

--- <context:component-scan>下可以拥有若干个<context:include-filter>和<context:exclude-filter>子节点

组件装配:<context:component-scan>元素还会自动注册AutowiredAnnoationBeanPostProcessor实例,该实例可以自动装配具有@Autowired和@Resource、@Inject注解的属性。

13、泛型依赖注入:

Spring4.x中可以为子类注入子类对应的泛型类型的成员变量的引用。

14、Spring AOP面向切面编程

动态代理设计模式的原理:使用一个代理将对象包装起来,然后用该代理对象取代原始对象,任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。

AOP的主要编程对象是切面(aspect),而切面模块快横切关注点。

在应用AOP编程时,仍然需要定义公共设施,但是可以明确的定义这个功能在哪里,以什么方式应用,并且不必修改受影响的类,这样一来横切关注点就被模块化到特殊的对象(切面)中了。

AOP的好处:

--- 每个事物逻辑位于一个位置,代码不分散,便于维护和升级;

--- 业务模块更简洁,只包含核心业务代码。

 

几个基本AOP术语:

--- 切面Aspect:横切关注点(跨越应用程序多个模块的功能)被模块化的特殊对象;

--- 通知Advice:切面必须要完成的工作;

--- 目标Target:被通知的对象;

--- 代理Proxy:向目标对象应用通知之后创建的对象;

--- 连接点JoinPoint:程序执行的某个特定位置;

--- 切点pointCut:每个类都拥有多个连接点,连接点是程序类中客观存在的事务。AOP通过切点定位到特定的连接点。连接点相当于数据库中的记录,切点则相当于查询条件。切点和连接点不是一对一的关系,一个切点匹配多个连接点,切点通过org.springframework.aop.Pointcut接口进行描述,它使用类和方法作为连接点的查询条件。

AspectJ:是java社区里面最完整最流行的框架,在Spring2.0以上的版本中,可以使用AspectJ注解和xml配置的方式进行使用。

--- 要在Spring中使用AspectJ注解,必须在classpath下包含AspectJ类库,aopalliance.jar、aspectj.weaver.jar、spring-aspectjs.jar

--- 将aop Schema添加到<beans>根元素中;

--- 要在SpringIOC容器中启动AspectJ注解支持,只要在Bean配置文件中定义一个空的XML元素<aop:aspectj-autoproxy>;

--- 当SpringIOC容器侦测到Bean配置文件中的<aop:aspect-autoproxy>元素时,会自动为与AspectJ切面匹配的Bean创建代理。

Spring AOP小结:

1)加入jar包;

2)在配置文件中加入AOP的命名空间;

3)基于注解的方式:

--- 在配置文件中加入如下配置<aop:aspect-autoproxy>

   --- 把横切关注点的代码抽象到切面的类中,切面首先是一个IOC中的bean,即加入@Component注解;

--- 切面还需要加入@Aspect注解;然后在类中申明各种通知(申明一个方法,然后在方法上加上如下通知注解):

   @Before:前置通知,在方法执行之前执行;

   @After:后置通知,在方法执行之后执行;

   @AfterRunning:返回通知,在方法返回结果之后执行;

   @AfterThrowing:异常通知,在方法抛出异常之后;

   @Around:环绕通知,围绕着方法执行。

--- 可以在通知方法中申明一个类型为JoinPoint的参数,然后就是访问连接细节,如方法名和参数值。

 

使用@Order(1)来指定多个切面的优先级,值越小优先级越高。

 

Spring的原理:

Spring的一个重要的设计模式就是抽象工厂方法和模板方法模式。另外AOP面向方面编程使用的设计模式是动态代理模式:

代理有两种方式:

1)静态代理:

针对每一个具体的类分别编写代理类;

针对一个接口编写一个代理类。

2)动态代理:

针对一个方面编写一个InvocationHandler,然后借用JDK中的反射包中的Proxy类为各种接口动态生成相应的代理类。

动态代理和静态代理的区别?

静态代理:由程序员创建,再对其编译。在程序运行之前.class文件已经存在了。动态代理:在程序运行时,运用反射的机制动态创建而完成。无需程序员手动编写代码,利用jdk的动态代理机制即可,不仅简化了编程工作,且提高了软件的可扩展性,因为java的反射机制可以生成任意类型的动态代理。 动态代理使用场景:不允许直接访问某些类,对访问要做特殊处理;或者对原始方法进行统一的扩展,例如日志的记录。

Spring IOC使用了单例模式,在使用时只创建一个全局对象,也可以在配置文件中进行多实例的配置。

Spring的事务管理:

事务就是对一系列的数据库操作(比如插入多条数据),进行统一的提交或者回滚操作,如果插入成功则一起成功,如果插入失败则一起失败。这样可以防止脏数据。

 

posted on 2017-03-10 17:31  吴容  阅读(175)  评论(0编辑  收藏  举报

导航