JavaWeb中的Spring概述

Spring是一个开源框架,其主要优势就是其是分层框架,可以让开发者自由使用哪些组件。

Spring主要由7个模块组成,每个模块都可以单独存在,也可以多个模块共同使用。

我们先不说模块,我们先说Spring的两个主要概念:

1.控制反转:顾名思义,控制某个对象的权利从自己手中移到了Spring手中。

比如:原本在程序的主函数中我需要一个猫对象,老鼠对象,狮子对象等等,那么我就需要手动new一个猫对象,老鼠对象,狮子对象等等。。.

而使用了Spring之后,现在我不需要手动new一个对象,我只需要将这些猫对象,老鼠对象,狮子对象等等这些类的的位置告诉Spring,让他去管理,当我想要获取这些对象的时候我告诉Spring一下,我需要这些对象,你给我new一个,spring就能给我new一个,完全省去不必要的繁琐代码等等。

未使用Spring前的代码:

创建主函数:

package com.strategy.jpa;

public class animal {

	public static void main(String[] args) {
		Cat cat=new Cat();
		cat.setAge(1);
		cat.setName("猫咪");
		
		Mouse mouse=new Mouse();
		mouse.setAge(2);
		mouse.setName("米老鼠");

	}

}

创建两个动物类Cat和Mouse:

package com.strategy.jpa;

public class Cat {

	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

package com.strategy.jpa;

public class Mouse {
	private String name;
	private int age;
	public Mouse()
	{
		
	}
	
	public Mouse(String name,int age)
	{
		this.name=name;
		this.age=age;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public void Cry()
	{
		System.out.println("叽叽");
	}
}

使用Spring后的代码: 首先添加Spring.jar包(这个就不再多说了)

创建beans.xml,用来配置相关的bean.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean id="cat" class="com.strategy.jpa.Cat">
        <property name="name" value="喵咪"/>
        <property name="age" value="1"/>
    </bean>
     <bean id="mouse" class="com.strategy.jpa.Mouse">
        <property name="name" value="米老鼠"/>
        <property name="age" value="2"/>
    </bean>
</beans>
在主函数添加下列语句:
package com.strategy.jpa;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class animal {

	public static void main(String[] args) {
		
	ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");//读取beans.xml中的内容
        Cat p = ctx.getBean("cat",Cat.class);//创建bean的引用对象
        p.Cry();
		
	}

}
有的人会疑惑,方便到那里了啊?

仔细想一下会发现,如果主函数需要多种动物类呢?

比如说,主函数还需要老虎类,狮子类,企鹅类对象等等,一个一个手动new确实很烦麻,通过xml的配置却方便一些。

在上面的代码中,我们只需要创建一个ApplicationContext,让其读取xml,然后根据我们的需要让Spring返给我们所需要的对象即可,具体方便在哪里呢?

当主函数不需要某个动物,或者说是需要同种动物的不同信息的时候(例如:原本需要小猫咪,现在需要大猫咪),只需要让spring创建一个另外的bean就行,不像之前的方法需要修改主函数中的代码就能达到同样的目的,还有不同对象之间联系也能因此而解耦合。

这里说的不是很清楚,大家可以看一下大话设计模式这本书,这本书对对象的解耦,以及工厂模式讲得非常清楚。

上述的代码中,我想说的是,Spring的控制反转利用反射和Key-Value(键值对),将配置文件的属性注入到对象中,做到随时获取,随时有值,随时可用的目的。

因为是键值对,所以beans.xml中bean的id必须是唯一的。

上述的方式是通过set方式将xml中的属性注入到cat对象中的。

还有一种方式也能注入,它是:构造函数注入。

构造函数注入和set注入类似,只是多写了几句话来说明注入的参数要往构造函数的参数注入。代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean id="cat" class="com.strategy.jpa.Cat">
        <property name="name" value="喵咪"/>
        <property name="age" value="1"/>
    </bean>
     <bean id="mouse" class="com.strategy.jpa.Mouse">
        <property name="name" value="米老鼠"/>
        <property name="age" value="2"/>
    </bean>
    
	<bean id="mouse1" class="com.strategy.jpa.Mouse">
		<constructor-arg value="米老鼠" />
		<constructor-arg value="222" />
	</bean>
</beans>

还有一种是接口注入:spring不用这种方式,因为接口注入说到底也就是set注入,spring也就没用这种方式。

再说一下代码中的ApplicationContext,ApplicationContext是一个接口,他是BeanFactory的子接口。

ApplicationContext和BeanFactory都可以认为是spring中管理Bean的容器,因为调用时是通过接口去调用这两个接口的实现类的。

因为实现该接口的实现类是容器,所以可以通过接口去管理容器Beans,我们通常用ApplicationContext去管理beans.

这里要说一下实现类:ApplictionContext的实现类为FileSystemXmlApplicationContext和ClassPathXmlApplicationContext

FileSystemXmlApplicationContext:基于文件系统的XML配置文件创建ApplicationContext;

ClassPathXmlApplicationContext:基于类加载路径下的xml配置文件创建ApplicationContext。

看不懂无所谓,你只要知道上面两个实现类的作用是,通过不同的寻找方式,找到xml然后创建ApplicationContext

其实,Spring加载beans.xml文件时,给beans中的bean写数据都是有一个流程的,这个流程和JavaWeb中的Listener很相似,不再过多阐述。

想要了解的可以看下面的链接:http://blog.csdn.net/u011704894/article/details/44407145

看不懂的可以看我的一篇文章:http://blog.csdn.net/u012605477/article/details/75308241

注意:ApplicationContext和application(ServletContext)是两码事,前者针对Spring而言,后者针对JSP而言。


2.面向切面:就是将一些方法或者其他操作当成一个切面。

比如:拿支付宝取钱举例,每当我们向朋友转账,查询自己余额,修改密码等操作时。我们都需要进行一个操作,那就是登录验证,在以往的编码中,登录验证分别放到每个模块中。

比如说,向朋友转账模块里有个登录验证,查询自己余额有个登录验证,现在我们把这个登录验证提取出来,让三者都能使用,进行相关操作时都能使用该验证,这个时候这个验证就叫做切面。

从代码的层面讲:就是编写一个切面类,然后在xml中将这个切面类交给aop框架管理,然后再在xml中声明一个切点(这个切点就是上面例子所说的登录验证方法),然后再在xml文件中的【切点前后】执行一下【切面类的相关方法】,供其对切点进行处理。

下面为代码:

切点类:

package com.strategy.jpa;

import org.springframework.stereotype.Repository;

//切点类方法
public class SpringAopDemo {
		public void show(){
			System.out.println("执行了切点的show方法");
	}
}
切面类:

package com.strategy.jpa;

import org.aspectj.lang.ProceedingJoinPoint;

//切面类
public class SpringAop {

	public void beforeShow(){
		System.out.println("执行aop切点方法前");
	}
	public void afterShow(){
		System.out.println("执行aop切点方法后");
	}
	/*	这里引用了Aop框架*/
	public void around(ProceedingJoinPoint joinpoint){
		System.out.println("开始执行aop切点方法");
		long start = System.currentTimeMillis();
		try {
			joinpoint.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		long end = System.currentTimeMillis();
		System.out.println("执行aop切点方法用时: "+(end-start)+" ms");
	}
}

beans.xml的配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans     
                        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd    
                        http://www.springframework.org/schema/aop     
                        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd    
                        http://www.springframework.org/schema/tx     
                        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd    
                        http://www.springframework.org/schema/context     
                        http://www.springframework.org/schema/context/spring-context-4.0.xsd"
	default-lazy-init="true">

	<!--spring可以自动去扫描base-pack下面或者子包下面的Java文件,如果扫描到有@Component @Controller@Service@Repository等这些注解的类,则把这些类注册为bean -->
	<!-- 名称不一样是因为这样可以对不同功能的bean进行分类 -->
	<!-- 这里将SpringAopDemo纳入了Spring管理 -->
	<context:component-scan base-package="com.strategy.jpa" />
	

	<bean id="springAopDemo" class="com.strategy.jpa.SpringAopDemo" />

	<!-- 将我们的切面类声明为一个bean -->
	<bean id="springAop" class="com.strategy.jpa.SpringAop" />
	<!-- 进行切面配置 -->
	<aop:config>
		<!-- 将切面类注入到aop框架中 -->
		<aop:aspect ref="springAop">
			<!-- 声明一个切点,切点的意思是,哪些方法需要被执行aop,这里指定SpringAopDemo.show(..)需要执行aop方法,并对需要执行AOP的方法设定id -->
			<aop:pointcut expression="execution(* com.strategy.jpa.SpringAopDemo.show(..))"
				id="performance" />
			<!-- 下面的before就是在标注的方法id前后,执行相关操作。 -->
			<aop:before method="beforeShow" pointcut-ref="performance" />
			<aop:after method="afterShow" pointcut-ref="performance" />
			<aop:around method="around" pointcut-ref="performance" />
		</aop:aspect>
	</aop:config>


</beans>
主函数的调用:

package com.strategy.jpa;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class animal {

	public static void main(String[] args) {
	ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");//读取bean.xml中的内容
        SpringAopDemo aopDemo=ctx.getBean("springAopDemo",SpringAopDemo.class);
        aopDemo.show();
	}

}

运行结果

是否和Servlet的创建销毁过程类似呢?

只不过Servlet的创建有init方法进行初始化,执行有Service方法操作,销毁有destory方法。

而aop这里变成了切面的方式,即通过xml配置的方式,根据自己抉择是否需要init方法和destory方法。

名称不同,方法的功能不同,但调用的顺序类同,操作异曲同工。

至此,应该大概明白了AOP能做什么了,如果你想了解更多,请看下面这位大神的博客。

http://blog.csdn.net/yunshixin/article/details/52444049


以上对Spring的bean配置都是通过xml进行配置的,对于新上手者看起来很直观,但是写的代码多了xml就很繁琐了,所以要换一种配置方式,即

Spring的注解使用方式:

1.在benas.xml中配置spring要管理的bean,即指定包下的bean(注解类)归于spring管理.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans     
                        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd    
                        http://www.springframework.org/schema/aop     
                        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd    
                        http://www.springframework.org/schema/tx     
                        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd    
                        http://www.springframework.org/schema/context     
                        http://www.springframework.org/schema/context/spring-context-4.0.xsd"
	default-lazy-init="true">
	<!--spring可以自动去扫描base-pack下面或者子包下面的Java文件,如果扫描到有@Component @Controller@Service@@Repository等这些注解的类,则把这些类注册为bean -->
	<!-- 名称不一样是因为这样可以对不同功能的bean进行分类 -->
	<!-- 这里将SpringAopDemo纳入了Spring管理 -->
	<context:component-scan base-package="com.spring.demo2" />

</beans>

主函数代码:

package com.spring.demo2;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class animal {

	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");// 读取bean.xml中的内容
		Cat cat = (Cat) ctx.getBean("cat");
		cat.Cry();
		Mouse mouse = (Mouse) ctx.getBean("mouse");
		mouse.Cry();
	}
}
实体类Cat和Mouse代码:

package com.spring.demo2;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;

@Repository 
public class Cat {

	@Value("我的名字叫猫咪")
	private String name;
	private int age;

	public void Cry()
	{
		System.out.println(this.name);
		System.out.println("喵喵");
	}
}
package com.spring.demo2;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;

@Repository 
public class Mouse {

	@Value("我的名字叫老鼠")
	private String name;
	private int age;

	public void Cry()
	{
		System.out.println(this.name);
		System.out.println("叽叽");
	}

}
运行结果:

原本需要在bean.xml中的配置bean,现在不需要了,原本需要在xml中配置bean的属性,现在也不需要了。

由此可知,spring的注解配置十分的方便,只需要在指定的类上加上注解即可。

注意:加上注解的bean类,通过获取其ApplicationContext获取的时候,一定要将该类的名称首字母小写,这是spring定义的。

不然获取不到,会产生以下错误。


spring的基本用法讲完了,但是Spring注解的分类与区别还未叙述,这点东西太多了,有点说不完,建个参考下面大神的博客,写的也挺详细。

http://blog.csdn.net/xyh820/article/details/7303330/


猜你喜欢

转载自blog.csdn.net/u012605477/article/details/76020136
今日推荐