spring
spring框架介绍
spring是一个轻量级的,一站式的潜在Stroe。spring是模块化的,允许只使用所学要组件,不必引入其他组件。
可以将IOC容器与任何Web框架一起使用,也可以以仅使用Hibernate集成代码或JDBC抽象层。
spring框架支持声名事务管理,通过RMI或Web服务对逻辑的远程访问一级适用于持久化数据的各种选项。
提供了功能齐全的MVC框架,能够将AOP透明的集中到软件中。
特性
spring框架被设计为非侵入式的,这意味着域逻辑代码通常不依赖于客户本身。在集成层(例如数据访问层)中,将存在对数据访问技术和spring库的某些依赖关系。但是,将这些依赖与其余代码库隔离起来应该很容易。
spring springMVC SpringBoot的关系
springMVC <spring<springBoot
springBoot就是一个大框架包含了很多东西,其中spring是最核心的内容之一,spring中也包含springMVC
springMVC只是spring处理web层请求的一个模块
地位
spring在java应用程序中的NO.1,目前无人可以撼动,存在事件久远,影响深远
spring的优点
1、方便解耦,简化开发
Spring就是一个大工厂,可以将对象的成绩和依赖关系的维护。交给spring管理
2、AOP编程的支持
spring提供面向切面编程,可以实现对程序进行权限拦截,运行监控等功能
3.声名事务的支持
通过配置就可以完成对事务的管理,无需手动编程
4.方便程序测试
spring对junit4支持。可以通过注解方便的测试spring程序
5.方便集成各种优秀的框架
spring不排斥各种优秀的开源框架,其内部提供了各种优秀的框架直接支持(如:Strut.Hbernates,Mbaties等)。
6,降低JavaEEAPI的使用难度
spring对javaEE中一些非常难用的API(如:JDBC,JavaMail,远程调用等),都提供了封装,使这些API的使用难度大大降低
简易的工厂模式
代码语言:javascript复制public class Person {
public int id;
}
public class Student extends Person {
public int num;
}
public class Person {
public int id;
}
public class Factory {
private final static String STUDENT="student";
private final static String TEACHER="teacher";
public Person getPerson(String str) {
if(str.equals(STUDENT)) {
return new Student();
}else if(str.equals(TEACHER)) {
return new Teacher();
}else {
return null;
}
}
}
class Test1 {
@Test
void test() {
Factory factory = new Factory();
Student student =(Student) factory.getPerson("student");
System.out.println(student.toString());
}
}
spring框架中不需要我们new工厂类,可以交给容器去做
junit4
一个简易的java单元测试框架,使用非常广泛
在测试方法上使用@Test注解即可
在测试方法中我们可以使用print方法进行输出,也可以使用各种的日志框架来打印日志文件。
还可以使用几个注解来初始化和清理测试方法使用的数据
@Before注解,测试方法使用前调用的方法
@After注解,测试方法使用后调用的方法
核心容器(Core Container)
Core 和Beans模块提供了spring最基础的功能,提供IOC和依赖注入。
基础概念是BeanFactory(Bena工厂),它提供Factory模式的经典实现来消除对程序单利模式的需要,并真正允许你从程序逻辑中分离出依赖关系和配置。
Context模块是基于Core和Bean来构建的,它提供了用一种框架风格的方式来访问对象。
Context封装包继承了beans包的功能,还增加了国际化(l18N),事件传播,资源装载,以及透明创建上下文。
Expression Language,表达式预压模块,提供了在运行期间查询和操作对象图的强大能力。支持访问和修改属性,方法调用,支持访问及修改数组,容器,和索引器,命名变量,支持算数和逻辑运算,支持spring容器获取Bean,它也支持列表投影,选择和一般的列表聚合等。
数据访问/集成部分(Data Access/Integration)
JDBC模块,提供对JDBC的抽象,它可以消除冗长的JDBC编码和解析数据库厂商特有的错误代码
ORM模块,提供了常用的“对象/关系”映射API的抽象层。包含JPA,JDO,Hibernate和iBeatis,利用ORM封装包,可以混合使用spring提供的特性进行"对象/关系"映射,如简单的声名事务管理
OXM模块,提供一个支持Object和XML进行映射的抽象层。包含JAXB,Castor,XMLBeans,JiBX和Stream
JMS 模块,提供一套"消息生产者,消费者"模板用于跟家简单的使用,JMS,JMS用于在两个程序之间,或分布式系统中发送消息,进行异步通信
Transaction模块 ,支持程序通过简单声名事务管理,只要是spring管理对象都能得到spring对象管理事务的好处,即使是POJO,也可以为他们提供事务。
web
web-socket模块,websocket protocol是HTML5一种新的协议。实现了浏览器与服务器全双工通信,spring支持websocket通信。
web模块,提供了基础的web功能。如多文件上传,集成IOC容器,远程过程访问以及对webservice支持,并提供一个RestTemplate类来提供方便的Restful service访问
web-servlet模块,提供web应用的model-view-controller(MVC)实现。springMVC 框架提供了基于注解的请求资源注入,跟接单的数据绑定,数据验证等一套非常易用的JSP标签,完全无缝与spring其他技术协作。
web-portlet模块,提供了在protlet环境下的MVC实现
aop
提供了符合aop联盟规范的面向切面的编程实现,让你可以定义如方法拦截器和切入点,从逻辑上讲,可以减弱代码的功能耦合,强袭的被分离。而且,利用源码级的元数据功能吗,还可以将各种行为信息合并到代码中。
aspects
提供了与aspectj的集成功能,aspect是一个功能强大且成熟的AOP框架
instrumentation
提供了一些类级的工具支持和ClassLoader级的实现,可以在一些特定的应用服务器中使用
messaging
该模块提供了对消息传递体系结构和协议的支持。
Test
支持使用junit4和spring组件进行单元测试和集成测试
Bean的生命周期
sprin只帮我们管理单例模式Bean的完整生命周期,对于propertype的bean,spring在创建好交给使用者之后则不会在管理后续的生命周期。
步骤
1.实例化一个Bean
2.按照spring上下文对实例化的Bean进行配置,也就是IOC注入(依赖注入);
3.如果这个bena实现了BeanNameAWare接口,会调用它实现的setBeanName(String)方法,传的参数就是spring配置文件中Bean的id值
4..如果这个bena实现了BeanNameAWare接口,会调用它实现的setBeanName(BeanFactory)方法,传的参数就是spring工厂自身
5.如果这个Bean实现了AppellationContextAware接口,会调用setApplicationConetext(ApplictaionContext)方法,出入Spring的上下文
6.如果这个Bean关联了BranPostProcessor接口,将会调用postProcessBeforerlnitialization(Object obj,String s)方法(开始前方法)
BranPostProcessor经常被用作是Bean内容的更改,并且由于是在Bean初始化结束时调用那个方法,也可被应用于内存和缓存技术。
7.如果Bean在Spring配置文件中配置了init-method属性会自动调配置的初始化方法
8.如果这个Bean关联了BranPostProcessor接口,将会调用postProcessAfterlnitialization(Object obj,String s)方法(结束后方法)
9.当Bean不在需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用那个实现的destroy()方法
10.最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用七配置的销毁方法
beans标签的属性
属性名 | 作用 |
---|---|
default-autowire-candidates | 是否接收自动装配,如果是false,namebeans标签下的所有字bean都不接受自动装配。默认是true |
default-destroy-method | 指定销毁的方法。如果子bean指定了销毁方法就用指定的,不会实现bean的销毁方法 |
default-init-method | 指定初始化方法。原理和销毁一致 |
default-lazy-init | 是否延迟初始化。值为(TRUE)要延迟,设了这个属性所有的子bean都会延迟。如果子bean设了这个属相,name自己的优先生效。节约项目的启动时间(了解) |
profile | 指定一类bean配置 |
default-autowire | 自动装配模式。若子bean没设置autowire,就用beans的。要慎用此属性,它省略的细节,容易产生潜在的错误。byType和byName的区别:byName 如果有其他的bean的id和其属性名一致,会自动注入;byType : 类型一致就会注入,如果有两个就会报错 |
spring整合 junit4测试
@RunWith 用于指定junit运行环境,是junit提供给其他框架测试环境接口扩展,为了便于使用spring的依赖注spring提供了org.springframework.test.context.junit4.SpringJUnit4ClassRunner作为Junit测试环境
@ContextConfiguration导入配置文件
如果有多个配置文件
@ContextConfiguration(locations = { classpath:spring-bean1.xml", "classpath:spring-bean2.xml" })
控制反转(IOC)
一种设计思想(将对象交给容器管理,不需我们再去new对象,可以由容器创建对象提供 给我们)
依赖注入(DI)
类在运行的时候依赖IOC容器,在需要某个对象的时候去注入对象
面向切面(AOP)
通过预编译的方式和运行期间动态代理,实现程序功能的统一维护的一种技术。
利用AOP可以对业务逻辑的各个部分进行分割,从而使业务逻辑各个部分之间耦合低,提高了程序的复用性,提高了开发效率。
主要作用于: 日志记录,性能统计,安全控制,事务处理,异常处理
bean标签
属性 | 描述 |
---|---|
id | id标签是bean标签的唯一标识,在IOC容器中bean标签不能出现两个重复的id,否则报错 |
name | 名称标识,一个bean标签可以有多个name属性 |
class | 全类名路径 |
init-method | 在创建一个bean之后调用这个方法,初始化方法必须是无参构造方法 |
destory-method | 在销毁前调用指定的方法。必需满足scope=singleton,并且destory方法的参数不能超过1个,参数类型只能为boolean |
scope | 作用范围 singloton:单例模式,指该bean在spring容器中只有一个对象,所哟普通过getBean获取的对象都是同一个对象 property:只要重新获取该标签,都将返回一个不同的对象 request:在一次http请求中对应一个Bean,类似于servlet session:在一次会话中对应一个Bean |
autowire | deafult(默认):采用父级标签Beans中的default-autowire属性 byName:通过属性名称自动装配。假如一个类中的对象名称为name,name根据id='name'找到Bean进行装配,类必须提供setName方法。 byType:根据属性类型来找配置文件中配置的class类型一致的bean来装配,如果找到多个就报异常,如果没找到,则不执行装配操作也不报异常 no:不执行自动装配操作,只能用ref标签进行装配 constructor:根据构造器中参数类型来自动装配,如果找到多个类型一致的bean,抛出异常,如果一个都没找到,不执行自动装配操作,但是抛出异常(这是和byType不同的地方)。 |
parent | 指定bean的父类,但class属性失效 |
primary | 当一个bean出现多个候选者的时候,会优先使用设置了primary=true属性的bean来自动装配 |
lazy-init | 设置bean对象是否懒加载,如果值为true,则在第一次用到bean的时候才实例化对象,否则在初始化spring容器是加载单例bean对象。(不是单例不会实例化) |
abstract | 设置有个bean是否为抽象类,值为true,这个bean不能被实例化 |
id 和 name的区别
id属性必须满足xml的命名规范,因其id其实是xml中做了限定的。不能以数字,符号开头,不能有空格。
name属性没有这些限定
bean常用的子标签
标签名称 | 属性 |
---|---|
property | 自动注入javabean的成员变量 |
constructor-arg | 构造器参数(顺序注入),这种方法会按照顺序注入构造器的参数 |
四种实例化bean的方式
使用构造器实例bean
这是最简单的方法,spring IOC容器能使用默认无参构造器,也能使用有参构造器两种方式进行实例化bena
使用无参构造器实例bean,class指定的实体类必须有无参构造器
代码语言:javascript复制<bean name="people" class="pojo.People"></bean>
使用有参构造器,用constructor-arg指定构造器参数的值,index表示下标,value表示值,也可以指定引用,用ref引用另一个Bean的定义
代码语言:javascript复制 <bean class="kj08.pojo.Student" id="student" >
<constructor-arg index="0" value="1"></constructor-arg>
<constructor-arg index="1" value="1"></constructor-arg>
<constructor-arg index="2" value="1"></constructor-arg>
</bean>
使用静态工厂实例bean
这种方式出了必须指定class属性,还要指定factory-method属性,指定实例化的方法
使用静态工厂也可以指定方法参数,springIOC容器将调用此方法指定的方法来获取
代码语言:javascript复制public class Hello {
private String str;
public String getstr() {
return str;
}
public void setstr(string str) {
this.str = str;
}
public Hello(String str){
this.str = str;
}
public Hello() {
}
public class HelloInstanceFactory{
public static Hello newInstanceHello(String message) {
return new Hello(message);
}
}
代码语言:javascript复制<bean id="hello" class="com.nieshenkuan.staticFactory. HelloInstanceFactory"
factory-method="newInstanceHello">
<constructor-arg index="0" value="helloworld! "></constructor-arg>
</bean>
使用动态工厂实例bean
使用这种方法不能指定class属性,必须使用factory-mothed属性指定工厂Bean,facory-mothed指定实例化的方法,可以指定参数,使用方法和构造器一致
代码语言:javascript复制public class Hello {
private String str;
public String getstr() {
return str;
}
public void setstr(string str) {
this.str = str;
}
public Hello(String str){
this.str = str;
}
public Hello() {
}
public class HelloInstanceFactory1{
public Hello newInstanceHello(String message) {
return new Hello(message);
}
}
代码语言:javascript复制<bean id="beanInstanceFactory"class="com.nieshenkuan.staticFactory.HelloInstanceFactory"></bean>
<bean id="hello2"factory-bean="beanInstanceFactory"factory-method="newInstanceHello">
<constructor-arg index="e" value="Helloworld2!"></constructor-arg>
</bean>
使用值注入(set方法)实例bean
class属性指定要实例的实体类(全路径),property标签赋值,name是实体类中的字段名,value是赋予的值
代码语言:javascript复制<bean name="people" class="com.nieshenkuan.model. People" id="people">
<property name="name" value="nsk"></property>
<property name="age" value="24"></property>
</bean>
注入不同类型的值
代码语言:javascript复制package kj08.pojo;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class TestEntity {
private String specialCharacter1; // 特殊字符值1
private String specialCharacter2; // 特殊字符值2
private Student innerBean; // JavaBean类型
private List<String> list; // List类型
private String[] array; // 数组类型
private Set<String> set; // Set类型
private Map<String, String> map; // Map类型
private Properties props; // Properties类型
private String emptyValue; // 注入空字符串值
private String nullValue = "init value"; // 注入null值
public void setSpecialCharacter1(String specialCharacter1) {
this.specialCharacter1 = specialCharacter1;
}
public void setSpecialCharacter2(String specialCharacter2) {
this.specialCharacter2 = specialCharacter2;
}
public void setInnerBean(Student user) {
this.innerBean = user;
}
public void setList(List<String> list) {
this.list = list;
}
public void setArray(String[] array) {
this.array = array;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProps(Properties props) {
this.props = props;
}
public void setEmptyValue(String emptyValue) {
this.emptyValue = emptyValue;
}
public void setNullValue(String nullValue) {
this.nullValue = nullValue;
}
public void showValue() {
System.out.println("特殊字符1:" this.specialCharacter1);
System.out.println("特殊字符2:" this.specialCharacter2);
System.out.println("内部Bean:" this.innerBean.getStudentName());
System.out.println("List属性:" this.list);
System.out.println("数组属性[0]:" this.array[0]);
System.out.println("Set属性:" this.set);
System.out.println("Map属性:" this.map);
System.out.println("Properties属性:" this.props);
System.out.println("注入空字符串:[" this.emptyValue "]");
System.out.println("注入null值:" this.nullValue);
}
}
代码语言:javascript复制<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns: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="entity" class="entity.TestEntity">
<!-- 使用<![CDATA[]]>标记处理XML特 殊字符 -->
<property name="specialCharacter1">
<value><![CDATA[P&G]]></value>
</property>
<!-- 把XML特殊字符替换为实体引用 -->
<property name="specialCharacter2">
<value>P&G</value>
</property>
<!-- 定义内部Bean -->
<property name="innerBean">
<bean class="entity.User">
<property name="username">
<value>Mr. Inner</value>
</property>
</bean>
</property>
<!-- 注入List类型 -->
<property name="list">
<list>
<!-- 定义List中的元素 -->
<value>足球</value>
<value>篮球</value>
</list>
</property>
<!-- 注入数组类型 -->
<property name="array">
<list>
<!-- 定义数组中的元素 -->
<value>足球</value>
<value>篮球</value>
</list>
</property>
<!-- 注入Set类型 -->
<property name="set">
<set>
<!-- 定义Set或数组中的元素 -->
<value>足球</value>
<value>篮球</value>
</set>
</property>
<!-- 注入Map类型 -->
<property name="map">
<map>
<!-- 定义Map中的键值对 -->
<entry>
<key>
<value>football</value>
</key>
<value>足球</value>
</entry>
<entry>
<key>
<value>basketball</value>
</key>
<value>篮球</value>
</entry>
</map>
</property>
<!-- 注入Properties类型 -->
<property name="props">
<props>
<!-- 定义Properties中的键值对 -->
<prop key="football">足球</prop>
<prop key="basketball">篮球</prop>
</props>
</property>
<!-- 注入空字符串值 -->
<property name="emptyValue">
<value></value>
</property>
<!-- 注入null值 -->
<property name="nullValue">
<null/>
</property>
</bean>
</beans>
利用注解赋值
@value
如果属性简单就用这个注解进行赋值,复杂就用xml进行配置
使用这个注解之前在配置文件中加上
代码语言:javascript复制<context:component-scan base-package="xxx"/>扫描注解 xxx填写包名
@Autowire和@Resource
不同点:
1.@Autowire和@Resource都是在bean的注入时使用,@Resource不是spring的注解,他是java的,但spring支持该注解的注入
2.@Auotwire的装配顺序
@Auotwire注解是按照类型(byType)装配依赖对象,默认它要求依赖对象必需存在,如果允许null值,这是required属性为false。
1.看类型
2.定义的名称
3.字段名
3.@Resource装配顺序
@Resource默认按照ByName自动注入,有J2EE提供,需导入javax.annotation.Resource包。
@Resource有两个重要属性:name和type,二spring将@@Resource注解的name属性解析为bean的名字,而type则解析为bean的类型。
如果使用name属性,则使用ByName的自动注入策略,而使用type属性时则使用ByType自动注入策略。
如果既不定制name属性也不定制type属性,将通过反射机制使用byName自动注入策略
顺序:
1.如果同时指定了name和type属性,从spring上下文中找到唯一匹配的bean进行装配,找不到抛异常。
2.如果指定了name,从上下文中找名称(id)匹配的bean进行装配,找不到抛异常。
3.如果指定了type,从上下文中找到类似匹配的唯一bean进行装配,找不到或找到多个,都会抛异常。
4.如果没有指定name和type,自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。
2.共同点
两者都可以写在字段和setter方法shang。如果两者都写在字段上没那么就不需要在写setter方法。
注:最好是将@Resource放在setter方法上,这样更符合面向对象思想,用过get,set操作属性,而不是直接操作属性。
AOP
概念
1.切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象。
2.连接点(Join point):程序执行过程中的某个点,比如某个方法调用的时候或处理异常的时候。在springAOP中一个连接点代表一个方法的执行,可以在通知(Advice)中获取连接点的信息
3.通知(Advice):在切面(Aspect)的某个连接点(Join point)上执行的动作。许多AOP框架,包括spring都是已拦截器作为通知模型,并维护一个以连接点为中心的连接器链。(Advice当一个方法被AOP拦截到的时候要执行的代码)
4.切入点(Pointcut):匹配连接点(Join point)的断言。通知(Advice)和切入点表示关联,并在切入点匹配的任何连接点上面运行。
切入点表达式如何跟连接点匹配是AOP核心,spring默认使用Aspectj作为切入点语法。
(通过切入点表达式来确定哪些方法要进行拦截,被拦截的方法执行相应的Advice代码)
5.引入(Introduction):声名额外的方法或是属性。SprinAOP允许你向任何被通知(Advice)的对象引入新的接口(及其实体类)。
(AOP允许在运行时动态的向代理对象实现新的借接口来完成一些额外的功能并且不影响现有对象的功能)
6.目标对象(Traget object):被一个或对个切面(Aspect)所通知(Adivce)的对象,也称作被通知对象。
由于SpringAOP是通过运行时代理实现的,所以这个对象永远是被代理对象。
(所有的对象在AOP中都会生成一个代理类,AOP整个过程中都是针对代理类在进行处理)
7.AOP代理(AOP proxy):AOP框架创建的对象,用来实现切面契约(aspect contranct)(包括通知方法执行等功能)。
在Spring中AOP可以是JDK动态代理(面向接口)或者是CGLIB
8.织入(Weving):把切面(aspect)连接到其他的应用程序类型或者对象上,并创建一个被通知对象。这些乐意在编译时,类加载时和运行时完成。
spring和其他纯AOP框架一样,在运行时完成织入。
(把切面跟对象关联,并创建该对象的代理对象的过程)
通知(Advice)的类型
1.前置通知(Before adive):在某个连接点之前执行的通知,这个通知不能阻止连接点执行(除非抛出一个异常)
2.返回后通知(After returning advice):在某个连接点正常完成后执行的通知。(方法没有抛出异常)
3.抛出异常后通知(After (finally) adivce):当某个连接点抛出异常后执行的通知
4.后置通知(After (finally) advice):在某个连接点退出是执行的通知。(不论是正常返回还是发生异常退出)
5.环绕通知(Around advice):保卫一个连接点的通知,如方法调用。这是最强大的一个通知类型。
环绕通知可以在方法前后完成自定义的行为。
他也会选择是否继续执行连接点或直接返回他们紫的返回值或抛出异常来结束执行。
execution语法
语法为:execution(修饰符 返回值 包名.类名/接口名.方法名(参数列表))
返回值类型 方法名 参数必须要有
表示任意值 比如返回类型 方法名等
(..)表示可以代表所有参数,()代表一个参数,(*,String)代表第一个参数为任何值,第二参数为String类型。
AOP两种操作方式
配置文件形式
代码语言:javascript复制<?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:c="http://www.springframework.org/schema/c"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.3.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd ">
<bean name="student1" class="dasd.pojo.Student" >
<property name="id" value="1">
</property>
<property name="name" value="afeng">
</property>
</bean>
<bean id="teacher1" class="dasd.pojo.Teacher" >
<property name="id" value="1">
</property>
<property name="name" value="afeng">
</property>
</bean>
<bean id="stuAsp" class="dasd.asp.StudentAsp"></bean>
<bean id="StudentService" class="dasd.service.impl.StudentService"></bean>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(public void dasd.service.impl.StudentService.doSome(..)) "></aop:pointcut>
<aop:aspect id="stuAsp" ref="stuAsp">
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after-returning method="after" pointcut-ref="pointcut"/>
<aop:after-throwing method="throwAfter" pointcut-ref="pointcut"/>
<aop:after method="AfterFinally" pointcut-ref="pointcut"/>
<aop:around method="around" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
</beans>
代码语言:javascript复制package dasd.service;
public interface IStudentService {
public void doSome();
}
package dasd.service.impl;
import dasd.service.IStudentService;
public class StudentService implements IStudentService {
@Override
public void doSome() {
int i= 1/0;
System.out.println(i);
}
}
package dasd;
import dasd.pojo.Student;
import dasd.service.IStudentService;
import dasd.service.impl.StudentService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
@ContextConfiguration("classpath:spring-bean.xml")
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("dev")
public class App
{
@Autowired
IStudentService studentService;
@Test
public void doSome(){
studentService.doSome();
}
}
相关标签
标签名 | 作用 | 属性 |
---|---|---|
aop:config | 用于声名开始aop配置 | |
aop:aspect | 配置切面 | id:提供唯一标识 ref引用配置好的通知类bean的id |
aop:advsior | 配置切面 | 和aspect的区别:aspect引用普通的bean,advsior引用bean必须是adivce接口 |
aop:pointcut | 配置切入点表达式 | expression:定义切入点表达式 id:给切入点表达式提供唯一标识 |
aop:before | 配置前置通知 | method:指定通知方法的名称 pointcut:定义切入点表达式 pointcut-ref:定义切入点表达式的引用 |
aop:afte-returning | 配置后置通知,出了异常一定不会调用切面的方法 | method:指定通知方法的名称 pointcut:定义切入点表达式 pointcut-ref:定义切入点表达式的引用 |
aop:after-throwing | 配置异常通知,只有出现异常才会调用切面的方法 | method:指定通知方法的名称 pointcut:定义切入点表达式 pointcut-ref:定义切入点表达式的引用 |
aop:after | 配置最终通知,不管出不出异常都会调用切面的方法 | method:指定通知方法的名称 pointcut:定义切入点表达式 pointcut-ref:定义切入点表达式的引用 |
aop:around | 配置环绕通知 | method:指定通知方法的名称 pointcut:定义切入点表达式 pointcut-ref:定义切入点表达式的引用 |
注解方式
首先在bean.xml文件中添加配置
(1)Before:在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可
(2)AfterReturning:在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值
(3)AfterThrowing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名
来访问目标方法中所抛出的异常对象
(4)After:在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式
(5)Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint
代码语言:javascript复制 <context:component-scan base-package="xxx" />//IOC自动扫包
<aop:aspectj-autoproxy />//开启Spring AOP注解方式首先要配置
<aop:aspectj-autoproxy/>标签,Spring提供了JDK动态代理和CGLIB代理两种方式为目标类创建代理,默认情况下,如果目标类实现了一个以上的用户自定义的接口或者目标类本身就是接口,就会使用JDK动态代理,如果目标类本身不是接口并且没有实现任何接口,就会使用CGLIB代理,如果想强制使用CGLIB代理,则可以将属性proxy-target-class设置true,这两种代理方式在使用的时候有一些需要注意的事项,JDK动态代理是基于实现目标类的接口来创建代理类的,所以只有接口方法会被代理,其他方法不会被代理,而CGLIB代理是基于继承目标类实现的,所以不能被继承的方法(例如final修饰的方法、private修饰的方法等)是不能被代理的,建议尽量使用JDK动态代理的方式创建代理类
expose-proxy属性用来解决对象内部this调用无法被切面增强的问题,例如我们在A类的对象内部x方法中调用另外一个内部方法y时,y方法不会被切面增强,这时可以配置expose-proxy为true并将this.y()改为((A)AopContext.currentProxy()).y(),即可让y方法被切面增强
JDK动态代理与cglib动态代理区别
jdk创建对象的速度远大于cglib,这是由于cglib创建对象时需要操作字节码。cglib执行速度略大于jdk,所以比较适合单例模式。另外由于CGLIB的大部分类是直接对Java字节码进行操作,这样生成的类会在Java的永久堆中。如果动态代理操作过多,容易造成永久堆满,触发OutOfMemory异常。
代码语言:javascript复制<?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:c="http://www.springframework.org/schema/c"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.3.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd ">
<bean name="student1" class="dasd.pojo.Student" >
<property name="id" value="1">
</property>
<property name="name" value="afeng">
</property>
</bean>
<bean id="teacher1" class="dasd.pojo.Teacher" >
<property name="id" value="1">
</property>
<property name="name" value="afeng">
</property>
</bean>
<bean id="StudentService" class="dasd.service.impl.StudentService"></bean>
<!--<aop:config>
<aop:pointcut id="pointcut" expression="execution(public void dasd.service.impl.StudentService.doSome(..)) "></aop:pointcut>
<aop:aspect id="stuAsp" ref="stuAsp">
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after-returning method="after" pointcut-ref="pointcut"/>
<aop:after-throwing method="throwAfter" pointcut-ref="pointcut"/>
<aop:after method="AfterFinally" pointcut-ref="pointcut"/>
<aop:around method="around" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>-->
<context:component-scan base-package="dasd" />
<aop:aspectj-autoproxy />
</beans>
什么时候用AOP
1.不想改变原有实现类的时候
2.想批量对某些特定的类进行某些操作的时候
SpringMVC
简介
springweb 模型视图控制器(MVC)框架是围绕DispatcherServlet设计的,该框架将请求分配给处理程序,并具有客配置的处理程序Map,
视图分辨器,语言环境,时区和主题分辨器,以及对文件上传的支持。
默认处理程序基于@Controller和@RequestMapping注解,提供了多种灵活的处理方式。
Spring3.0的映入,@Controller注解还允许通过@PathVariable注解和其它功能来成绩Testful网站和应用程序
原则
针对扩展开放,针对修改关闭。
spring Web MVC核心类中的某些方法标记为final。不能覆盖这些方法来提供自己的行为。(不能进行重写和覆盖)
运行原理
1.客户端发送http请求,web服务器接收请求。(如果配置了DispatcherServlet的请求的映射路径,web容器将请求交给DispatcherServlet处理)
2.DispatcherServlet拿到相应的Handler后,根据请求的信息(URL,请求参数,HTTP方法)及HandlerMapping的配置找到处理请求的处理器(Handeler)
3.当DispatcherServlet找到相应的Handler后,通过HanderAdapter对Hander进行封装,再用统一的适配器接口调用。
4.在请求信息到达调用Handler的处理方法之前,SpringMVC会将请求信息以一定的方式转换并绑定到请求方法的入参,对入参的对象进行数据转换,数据格式化以及数据的校验等。 这些都处理完才真正调用Handler的处理方法进行相应的业务逻辑处理。
5.处理器完成业务处理后,将一个ModelAndView对象返回给DispatcherServlet,包含了逻辑视图和模型数据信息。
6.DispatcherServlet通过ViewResolver(视图解析器),将逻辑视图解析为真正的视图对象View。可以使jsp,html,xml,json等,得到真正的视图对象后,DispatcherServlet会根据ModelAndView对象中的模型数据对View进行视图渲染。最终客户端获得响应的消息。
Spring MVC框架的特点
1.角色划分清晰。Model,View,Conroller各司其职,耦合度低
2.灵活的配置功能。Spring的核心是IOC和AOP,统一可以实现在MVC上,把各种类的Bean组件配置在Spring容器中。
3.提供了大量的接口和实现类,方便各种场景的开发。
4.真正做到与View层的实现无关。
5.结合Spring的依赖注入,更好的应用了面向接口编程的思想。
6.可以与Spring无缝整合。
DisPatcherServlet
继承自HTTPServlet基类,统同样需要在web应用的web.xml配置文件下声名DisPatcherServlet依赖的Bean
逻辑视图和物理视图
逻辑试图:控制器方法返回一个字符串,或是通过ModelAndView.setViewName(String viewName)方法设置一个视图名,此时的视图成为一个逻辑视图,因为前端控制器需要通过视图解析器来解析逻辑视图,得到一个视图对象,然后才响应个客户端。
物理视图:在控制器方法中直接通过ModelAndView.setView(View v)方法设置视图对象,然后返回ModelAndView给前端控制器,这时的视图是物理视图,因为它前端控制器不需要在使用视图解析器来解析,直接将视图内容响应给客户端。
定制DisPatcherServlet的配置
可选参数 | 解释 |
---|---|
contextClass | 任意实现了WebApplicationContext接口的类。这个类hi初始化该servlet所要用到的上下文对象。默认情况下框架会使用一个XmlWebApplicationContext对象。 |
contextConfigLocation | 一个指定客上下文配置文件路径的字符串,该值会被传入给cintextClass所指定的上下文实例对象。这个字符串可以包含多个字符串,用逗号隔开,以此支持进行多个上下文的配置。重复定义的Bean,以最后加载的bean为准 |
namespace(重要) | WebApplicationContext的名称空间。默认是[servlet-name]-servlet |
请求
HTTP的请求报文分为请求行,请求头,请求体
Request Line:请求行
请求行分为三部分:请求方法,请求地址和协议以及版本,以CRLF(rn)结束。常用的定义方法有:GET和POST;RESTful接口常用的有
GET,POST,PUT,DELETE。
Requset Methods
只有POST,PUT,PATCH,这三种会包含请求体,其它的不包含请求体。
Header:请求头
header | 说明 |
---|---|
Accept | 指定客户端能够接收的内容类型 |
Accept-Charset | 客户端可以接收的字符编码集 |
Request Body请求体
根据应用场景的不同,HTTP请求的请求体有三种不同的形式。
1.application/json
application/json这个Content-Type作为响应头。用来告诉服务端消息主体是序列化后的JSON字符串。
JSON格式支持比键值对复杂的多的结构化数据。
2.text/xml
3.Query String:appli/x-www-form-urlencided
最常见的POST提交数据的方式。
浏览器的原生form表单,如果不设置emctype属性,就会以这种方式提交数据。
ModelAndView类
业务处理器调用模型层处理完用户请求后,把结果数据存储在该类的model属性中,把要返回的视图信息存储在该类的view属性中,然后让这个ModelAndView返回Spring MVC框架。框架通过调用配置文件中定义的视图解析器,对这个对象进行解析,最后把结果数据渲染在指定的页面上。
常用的构造方法
ModelAndView(String viewName)
持有View的名称返回,之后View被view resolver接口的实例解析。
ModelAndView(String viewName,Map model)
如果要返回Model对象,可以用Map来收集这些Model对象,然后设定给ModelAndView,使用下面这个版本的ModelAndView:
ModelAndView()
这个构造方法构造出来的ModelAndView不能直接使用,有误没有指定View,也没有绑定对应的model对象。 model对象不是必须的,但view对象是必须的。
这个构造方法构造的实例主要用来在以后往其中添加view设置和model对象。
往ModelAndView实设置view有两种方式:
1setViewName(String ViewName)这种方式是往参数中放入一个视图的名称(比较常用)
2.setView(View view)这种方式是往参数直接放入一个View对象。
View是一个接口,不是一个可以构造的具体类,需要谈过其他方式来获取View的实例。
往ModelAndView实设置model有三种方式:
addObject(Object modelObject)
addObject(String modelName,Object modelObject)
addAllObjects(Mao modelMap)
return new ModelAndView("redirect:/404.htm");重定向
注解
@Controller
声名该类为SpringMvc中的Controller控制器。
Controller控制器负责处理有DisPatcherServlet分发的请求,把用户的请求数据经过业务处理层处理后封装为一个Model,然后把这个Model返回给对应的View进行展示。
在SpringMVC中使用@Controller就无需继承特定的类或实现特定的接口,只需要使用@Controller注解标记一个类是Controller(控制器),然后使用@RequestMapping和@RequestParam等注解,定义URL(地址)请求和Controller之间的映射,这样Controller就可以被外界访问到。
@Controller标记在一个类上,这个类就是SpringMVC Controller对象。
分发处理器会扫描使用了该注解类的方法,并检测方法是否使用了@RequestMapping注解。
方法的返回值
返回ModelAndView:需要方法结束时,定义ModelAndView,将model和view分别进行设置。
返回void
在controller方法的形参上可以第一request和response,使用request和response指定响应结果。
返回String
return "xxxxx";逻辑视图名
return "redirect:/xxxxx"重定向
return "forward:xxxxx"转发
RequestMapping
@RequestMapping的作用是建立请求URL和处理方法之间的对应关系
@RequestMapping可以作用在方法和类上
作用在类上:第一级访问目录
作用在方法上:第二级访问目录
@RequestMapping的属性
path:指定请求路径的URL(地址)
value:和path属性一样
method:指定该方法的请求方式
params:限制请求参数的条件
headers:发送的请求中必须包含的请求头
produces:produces = "application/json;charset=utf-8" 等于 response.setContentType("application/json;charset=utf-8");
@ModelAttribute
方法上注释
被@ModelAttribute注释的方法会在次controller每个方法执行前被执行,因此对于一个controller映射多个URL的用法来说要谨慎使用
参数上注释
@ModelAttribute注释一个方法的参数
代码语言:javascript复制@Controller
public class HelloWorldController {
@ModelAttribute("user")
public User addAccount() {
return new User("jz","123");
}
@RequestMapping(value = "/helloWorld")
public String helloWorld(@ModelAttribute("user") User user) {
user.setUserName("jizhou");
return "helloWorld";
}
}
//@ModelAttribute("user") User user注释方法参数,参数user的值来源于addAccount()方法中的model属性。此时如果方法体没有标注@SessionAttributes("user"),那么scope为request,如果标注了,那么scope为session
从Form表单或URL参数中获取(实际上,不做此注释也能拿到user对象)
代码语言:javascript复制@Controller
public class HelloWorldController {
@RequestMapping(value = "/helloWorld")
public String helloWorld(@ModelAttribute User user) {
return "helloWorld";
}
}
注意这时候这个User类一定要有无参的构造函数
@SessionAttributes
往session作用域中进行赋值,一般不用。
@PathVariable
REST 风格
RESTRepresentational State Transfer
(资源)表现层状态转化,用URL定位资源,用HTTP描述操作。
@RequestParam与@RequestBody
@RequestParam
接受的参数来自于请求头中,通常用于GET请求。
@RequestParam有三个配置参数:
1.required :表示是否为必须的,默认为true,必须。
2.defaultValue:设置请求参数的默认值
3.value:为接收url的参数名称
@RequestParam用来处理Content-Type为application/x-www-form-urlencoded编码的内容
@RequestParam也可以用于其他类型的请求,如POST,DELETE等请求。
@RequestBody
就收的参数来自于requestBody(请求体)中。一般用作处理application/json,application/xml等类型的数据。
使用@requestBody注解可以将body里所有的json数据传到后端,后端在进行解析。
在后端的同一个接收方法里@requestBody与@RequestParam()可以同时存在,@RequestParam可以有多个,@requestBody只能有一个。在使用@RequestParam的时候,不加注解的效果与@RequestParam类似。
@ResponseBody
通常用在控制层(Controller)上,用于将Controller的方法返回的对象,通过SpringMVC提供的HttpMessageConverter接口转换为指定格式的数据,通过Response响应给客户端。
如果返回的是字符串,直接将字符串写到客户端。
如果是对象,此时会将对象转化为json字符串然后写到客户端。
@RESTContribute
@Controller和@ResponseBody
@GetMapping @POTMapping @PUTMapping @DELETEMapping
什么是RESTful风格
一种架构风格,表述性状态转移,不是软件也不是标准,而是一种思想,不依赖于任何通信协议,但是开发时要成功映射到某些协议时,也需要遵循器标准。但不包含对通信协议的更改。
特征
1.通过url地址来表示资源,系统中的每个对象或资源都可以通过url来获取。
2.统一接口,显示的使用HTTP方法,来进行映射。
3.资源多重反射,通过url地址访问的每个资源都可以根据客户端的规定进行返回。