Spring简介
Spring是Java的开源企业应用程序开发框架,它为 Java beans控制容器的翻转。最初由Rod Johnson在2003年6月基于Apache2.0许可证发布。 Spring框架处理底层,使我们能够专注于应用程序逻辑。 Spring能够从POJOs(Plain Old Java Objects)非侵入式的构建应用程序。比如: •不需要处理servlet或servlet API,Java方法可以处理HTTP POST / GET请求。 •不需要处理web服务API,Java方法可提供RESTful Web服务 •不需要处理事务API,Java方法可以执行数据库事务 •不需要处理远程API,本地Java方法使用RPC(remote procedure call) •不需要处理JMS API,Java方法可以使用和处理消息 •不需要处理JMX API,Java方法可以作为管理扩展
Spring的特性: •开源应用程序框架 •企业轻量级应用框架 •非侵入性(基于POJO) •模块化 •可扩展用于其他框架 •Java企业应用程序的事实标准
优势: •使用POJO、轻,非入侵 •通过依赖注入和接口定向实现松耦合 •通过aspect和共同约定实现声明式编程 •通过aspect和模板减少代码
Spring Framework的核心容器:
• Core and Beans:提供IOC(Inversion of control)和DI(dependency injection)
• Context:类似JNDI(Java Naming and Directory Interface,Java命名和目录接口),用于在框架中访问对象。
• 表示语言(Expression Language):SpEL,用于查询和修改对象图并评估数学表达式。
AOP模块 AOP是Spring面向方面编程的实现。它解耦业务逻辑和日志、安全等基础代码。
instrumentation模块 提供instrumentation类支持,通过MBean展示容器资源和帮助JMX管理。
消息模块 包含Spring Integration项目的关键抽象如Message、MessageChannel和的MessageHandler。
数据访问模块 •JDBC:JDBC抽象层 •ORM:为流行的对象关系映射提供集成层API,包括JPA,JDO,Hibernate和iBATIS •OXM:对象/ XML映射抽象层,实现了JAXB,Castor,XMLBeans的,JiBX和Xstream
•JMS:生产和消费消息 •事务:它支持programmatic和programmatic事务管理
web层 该网络层包括web,webmvc / servlet中,WebSocket和webmvc-portlet模块:
•Web:文件上传等基础组件。 •Webmvc: •Portlet •WebSocket
Spring项目涉及安全配置、Web应用程序、大数据、LDAP等。 Spring框架是其中一部分。 JNDI(Java Naming and Directory Interface,Java命名和目录接口)
Java相关的一些博客:
http://www.gualtierotesta.it/
IoC(Inversion of Control)和DI(dependency injection)经常不区分使用。IoC由IoC实现。
两种类型的依赖注入:
• Constructor injection
• Setter injection
比如定义:
1
2
3
4
<
bean
id
=
"bookLister"
class
=
"com.packt.di.BookLister"
>
<
constructor-arg
ref
=
"bookService"
/>
</
bean
>
<
bean
id
=
"bookService"
class
=
"com.packt.di.BookServiceImpl"
/>
等同于:
1
2
BookService service =
new
BookServiceImpl();
BookLister bookLister =
new
BookLister(service);
1
2
3
4
<
bean
id
=
"bookListerSetterInjection"
class
=
"com.packt.di.BookLister"
>
<
property
name
=
"bookService"
ref
=
"bookService"
/>
</
bean
>
<
bean
id
=
"bookService"
class
=
"com.packt.di.BookServiceImpl"
/>
等同于:
1
2
3
BookService service =
new
BookServiceImpl();
BookLister bookLister =
new
BookLister();
bookLister.setBookService(service);
Spring IoC container 即ApplicationContext。管理的容器叫bean,比如bookService就是bean,即Spring IoC container管理的对象。
bean的属性有:
class、name(即id)、scope、constructor-arg、properties、lazy-init(使用时才创建容器)、init-method 、destroy-method。
scope的取值有:
singleton:每个bean实例一个容器。实际上是每个bean实例一个classloader。
prototype:每个bean实例多个实例对象。
request:每个bean实例一个HTTP request。
session:每个bean实例一个HTTP session。
global-session:每个bean实例一个全局HTTP session。
生命周期:
第一个实例
前提: Maven和STS安装OK,都可以从Eclipse 市场安装。
新建Spring Starter Project项目,
Name:SpringOverview 注明名字前后不要有空格。
Type:Maven
其他用默认配置。
原有默认的SpringOverviewApplication类内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
package
com.example;
import
org.springframework.boot.SpringApplication;
import
org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public
class
SpringOverviewApplication {
public
static
void
main(String[] args) {
SpringApplication.run(SpringOverviewApplication.
class
, args);
}
}
删除包com.example下面的SpringOverviewApplication类。新建HelloWorld类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package
com.example;
public
class
HelloWorld {
private
String message;
public
String getMessage() {
return
message;
}
public
void
setMessage(String message) {
this
.message = message;
}
}
在src/main/resources新建 applicationContext.xml:
1
2
3
4
5
6
7
8
9
10
11
12
<?
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.xsd">
<
bean
id
=
"helloWorld"
class
=
"com.example.HelloWorld"
>
<
property
name
=
"message"
value
=
"Welcome to the Spring world"
>
</
property
>
</
bean
>
</
beans
>
com.example下面新建类HelloWorldExample:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package
com.example;
import
org.springframework.context.ApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
public
class
HelloWorldExample {
public
static
void
main(String[] args) {
ApplicationContext context =
new
ClassPathXmlApplicationContext(
"applicationContext.xml"
);
HelloWorld world = (HelloWorld)
context.getBean(
"helloWorld"
);
System.out.println(world.getMessage());
}
}
用Spring Boot App的方式执行:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
11
:
38
:
15.765
[main] DEBUG o.s.core.env.StandardEnvironment - Adding [systemProperties] PropertySource with lowest search precedence
11
:
38
:
15.768
[main] DEBUG o.s.core.env.StandardEnvironment - Adding [systemEnvironment] PropertySource with lowest search precedence
11
:
38
:
15.768
[main] DEBUG o.s.core.env.StandardEnvironment - Initialized StandardEnvironment with PropertySources [systemProperties,systemEnvironment]
11
:
38
:
15.770
[main] INFO o.s.c.s.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext
@71c7db30
: startup date [Thu Dec
31
11
:
38
:
15
CST
2015
]; root of context hierarchy
11
:
38
:
15.794
[main] DEBUG o.s.core.env.StandardEnvironment - Adding [systemProperties] PropertySource with lowest search precedence
11
:
38
:
15.795
[main] DEBUG o.s.core.env.StandardEnvironment - Adding [systemEnvironment] PropertySource with lowest search precedence
11
:
38
:
15.795
[main] DEBUG o.s.core.env.StandardEnvironment - Initialized StandardEnvironment with PropertySources [systemProperties,systemEnvironment]
11
:
38
:
15.801
[main] INFO o.s.b.f.xml.XmlBeanDefinitionReader - Loading XML bean definitions from
class
path resource [applicationContext.xml]
11
:
38
:
15.811
[main] DEBUG o.s.b.f.xml.DefaultDocumentLoader - Using JAXP provider [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl]
11
:
38
:
15.830
[main] DEBUG o.s.b.f.xml.PluggableSchemaResolver - Loading schema mappings from [META-INF/spring.schemas]
11
:
38
:
15.833
[main] DEBUG o.s.b.f.xml.PluggableSchemaResolver - Loaded schema mappings: {http:
//www.springframework.org/schema/cache/spring-cache-4.2.xsd=org/springframework/cache/config/spring-cache-4.2.xsd, http://www.springframework.org/schema/aop/spring-aop-4.1.xsd=org/springframework/aop/config/spring-aop-4.1.xsd, http://www.springframework.org/schema/context/spring-context-3.1.xsd=org/springframework/context/config/spring-context-3.1.xsd, http://www.springframework.org/schema/util/spring-util-3.0.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd, http://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-4.2.xsd, http://www.springframework.org/schema/aop/spring-aop-3.2.xsd=org/springframework/aop/config/spring-aop-3.2.xsd, http://www.springframework.org/schema/lang/spring-lang-4.1.xsd=org/springframework/scripting/config/spring-lang-4.1.xsd, http://www.springframework.org/schema/context/spring-context-4.0.xsd=org/springframework/context/config/spring-context-4.0.xsd, http://www.springframework.org/schema/beans/spring-beans-4.2.xsd=org/springframework/beans/factory/xml/spring-beans-4.2.xsd, http://www.springframework.org/schema/tool/spring-tool-4.1.xsd=org/springframework/beans/factory/xml/spring-tool-4.1.xsd, http://www.springframework.org/schema/lang/spring-lang-3.2.xsd=org/springframework/scripting/config/spring-lang-3.2.xsd, http://www.springframework.org/schema/cache/spring-cache-3.2.xsd=org/springframework/cache/config/spring-cache-3.2.xsd, http://www.springframework.org/schema/jee/spring-jee-4.1.xsd=org/springframework/ejb/config/spring-jee-4.1.xsd, http://www.springframework.org/schema/util/spring-util-2.0.xsd=org/springframework/beans/factory/xml/spring-util-2.0.xsd, http://www.springframework.org/schema/task/spring-task-4.2.xsd=org/springframework/scheduling/config/spring-task-4.2.xsd, http://www.springframework.org/schema/tool/spring-tool-3.2.xsd=org/springframework/beans/factory/xml/spring-tool-3.2.xsd, http://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context-4.2.xsd, http://www.springframework.org/schema/cache/spring-cache-4.1.xsd=org/springframework/cache/config/spring-cache-4.1.xsd, http://www.springframework.org/schema/aop/spring-aop-4.0.xsd=org/springframework/aop/config/spring-aop-4.0.xsd, http://www.springframework.org/schema/jee/spring-jee-3.2.xsd=org/springframework/ejb/config/spring-jee-3.2.xsd, http://www.springframework.org/schema/context/spring-context-3.0.xsd=org/springframework/context/config/spring-context-3.0.xsd, http://www.springframework.org/schema/util/spring-util-2.5.xsd=org/springframework/beans/factory/xml/spring-util-2.5.xsd, http://www.springframework.org/schema/beans/spring-beans-3.2.xsd=org/springframework/beans/factory/xml/spring-beans-3.2.xsd, http://www.springframework.org/schema/aop/spring-aop-3.1.xsd=org/springframework/aop/config/spring-aop-3.1.xsd, http://www.springframework.org/schema/lang/spring-lang-4.0.xsd=org/springframework/scripting/config/spring-lang-4.0.xsd, http://www.springframework.org/schema/beans/spring-beans-4.1.xsd=org/springframework/beans/factory/xml/spring-beans-4.1.xsd, http://www.springframework.org/schema/tool/spring-tool-4.0.xsd=org/springframework/beans/factory/xml/spring-tool-4.0.xsd, http://www.springframework.org/schema/lang/spring-lang-3.1.xsd=org/springframework/scripting/config/spring-lang-3.1.xsd, http://www.springframework.org/schema/cache/spring-cache-3.1.xsd=org/springframework/cache/config/spring-cache-3.1.xsd, http://www.springframework.org/schema/jee/spring-jee-4.0.xsd=org/springframework/ejb/config/spring-jee-4.0.xsd, http://www.springframework.org/schema/task/spring-task-4.1.xsd=org/springframework/scheduling/config/spring-task-4.1.xsd, http://www.springframework.org/schema/tool/spring-tool-3.1.xsd=org/springframework/beans/factory/xml/spring-tool-3.1.xsd, http://www.springframework.org/schema/cache/spring-cache-4.0.xsd=org/springframework/cache/config/spring-cache-4.0.xsd, http://www.springframework.org/schema/jee/spring-jee-3.1.xsd=org/springframework/ejb/config/spring-jee-3.1.xsd, http://www.springframework.org/schema/util/spring-util-4.2.xsd=org/springframework/beans/factory/xml/spring-util-4.2.xsd, http://www.springframework.org/schema/task/spring-task-3.2.xsd=org/springframework/scheduling/config/spring-task-3.2.xsd, http://www.springframework.org/schema/beans/spring-beans-3.1.xsd=org/springframework/beans/factory/xml/spring-beans-3.1.xsd, http://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-4.2.xsd, http://www.springframework.org/schema/aop/spring-aop-3.0.xsd=org/springframework/aop/config/spring-aop-3.0.xsd, http://www.springframework.org/schema/beans/spring-beans-4.0.xsd=org/springframework/beans/factory/xml/spring-beans-4.0.xsd, http://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-4.2.xsd, http://www.springframework.org/schema/lang/spring-lang-3.0.xsd=org/springframework/scripting/config/spring-lang-3.0.xsd, http://www.springframework.org/schema/context/spring-context-2.5.xsd=org/springframework/context/config/spring-context-2.5.xsd, http://www.springframework.org/schema/task/spring-task-4.0.xsd=org/springframework/scheduling/config/spring-task-4.0.xsd, http://www.springframework.org/schema/tool/spring-tool-3.0.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd, http://www.springframework.org/schema/aop/spring-aop-2.0.xsd=org/springframework/aop/config/spring-aop-2.0.xsd, http://www.springframework.org/schema/jee/spring-jee-3.0.xsd=org/springframework/ejb/config/spring-jee-3.0.xsd, http://www.springframework.org/schema/util/spring-util-4.1.xsd=org/springframework/beans/factory/xml/spring-util-4.1.xsd, http://www.springframework.org/schema/task/spring-task-3.1.xsd=org/springframework/scheduling/config/spring-task-3.1.xsd, http://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd, http://www.springframework.org/schema/jee/spring-jee.xsd=org/springframework/ejb/config/spring-jee-4.2.xsd, http://www.springframework.org/schema/aop/spring-aop-2.5.xsd=org/springframework/aop/config/spring-aop-2.5.xsd, http://www.springframework.org/schema/lang/spring-lang-2.0.xsd=org/springframework/scripting/config/spring-lang-2.0.xsd, http://www.springframework.org/schema/util/spring-util-3.2.xsd=org/springframework/beans/factory/xml/spring-util-3.2.xsd, http://www.springframework.org/schema/task/spring-task.xsd=org/springframework/scheduling/config/spring-task-4.2.xsd, http://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd, http://www.springframework.org/schema/lang/spring-lang-2.5.xsd=org/springframework/scripting/config/spring-lang-2.5.xsd, http://www.springframework.org/schema/context/spring-context-4.2.xsd=org/springframework/context/config/spring-context-4.2.xsd, http://www.springframework.org/schema/jee/spring-jee-2.0.xsd=org/springframework/ejb/config/spring-jee-2.0.xsd, http://www.springframework.org/schema/tool/spring-tool-2.5.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd, http://www.springframework.org/schema/jee/spring-jee-2.5.xsd=org/springframework/ejb/config/spring-jee-2.5.xsd, http://www.springframework.org/schema/util/spring-util-4.0.xsd=org/springframework/beans/factory/xml/spring-util-4.0.xsd, http://www.springframework.org/schema/task/spring-task-3.0.xsd=org/springframework/scheduling/config/spring-task-3.0.xsd, http://www.springframework.org/schema/aop/spring-aop-4.2.xsd=org/springframework/aop/config/spring-aop-4.2.xsd, http://www.springframework.org/schema/lang/spring-lang.xsd=org/springframework/scripting/config/spring-lang-4.2.xsd, http://www.springframework.org/schema/context/spring-context-3.2.xsd=org/springframework/context/config/spring-context-3.2.xsd, http://www.springframework.org/schema/util/spring-util-3.1.xsd=org/springframework/beans/factory/xml/spring-util-3.1.xsd, http://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd, http://www.springframework.org/schema/cache/spring-cache.xsd=org/springframework/cache/config/spring-cache-4.2.xsd, http://www.springframework.org/schema/lang/spring-lang-4.2.xsd=org/springframework/scripting/config/spring-lang-4.2.xsd, http://www.springframework.org/schema/context/spring-context-4.1.xsd=org/springframework/context/config/spring-context-4.1.xsd, http://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd, http://www.springframework.org/schema/tool/spring-tool-4.2.xsd=org/springframework/beans/factory/xml/spring-tool-4.2.xsd, http://www.springframework.org/schema/jee/spring-jee-4.2.xsd=org/springframework/ejb/config/spring-jee-4.2.xsd, http://www.springframework.org/schema/aop/spring-aop.xsd=org/springframework/aop/config/spring-aop-4.2.xsd}
11
:
38
:
15.833
[main] DEBUG o.s.b.f.xml.PluggableSchemaResolver - Found XML schema [http:
//www.springframework.org/schema/beans/spring-beans.xsd] in classpath: org/springframework/beans/factory/xml/spring-beans-4.2.xsd
11
:
38
:
15.862
[main] DEBUG o.s.b.f.x.DefaultBeanDefinitionDocumentReader - Loading bean definitions
11
:
38
:
15.871
[main] DEBUG o.s.b.f.xml.XmlBeanDefinitionReader - Loaded
1
bean definitions from location pattern [applicationContext.xml]
11
:
38
:
15.872
[main] DEBUG o.s.c.s.ClassPathXmlApplicationContext - Bean factory
for
org.springframework.context.support.ClassPathXmlApplicationContext
@71c7db30
: org.springframework.beans.factory.support.DefaultListableBeanFactory
@4d95d2a2
: defining beans [helloWorld]; root of factory hierarchy
11
:
38
:
15.888
[main] DEBUG o.s.c.s.ClassPathXmlApplicationContext - Unable to locate MessageSource with name
'messageSource'
: using
default
[org.springframework.context.support.DelegatingMessageSource
@11758f2a
]
11
:
38
:
15.889
[main] DEBUG o.s.c.s.ClassPathXmlApplicationContext - Unable to locate ApplicationEventMulticaster with name
'applicationEventMulticaster'
: using
default
[org.springframework.context.event.SimpleApplicationEventMulticaster
@4671e53b
]
11
:
38
:
15.890
[main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory
@4d95d2a2
: defining beans [helloWorld]; root of factory hierarchy
11
:
38
:
15.890
[main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean
'helloWorld'
11
:
38
:
15.890
[main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean
'helloWorld'
11
:
38
:
15.898
[main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean
'helloWorld'
to allow
for
resolving potential circular references
11
:
38
:
15.914
[main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean
'helloWorld'
11
:
38
:
15.915
[main] DEBUG o.s.c.s.ClassPathXmlApplicationContext - Unable to locate LifecycleProcessor with name
'lifecycleProcessor'
: using
default
[org.springframework.context.support.DefaultLifecycleProcessor
@2f8f5f62
]
11
:
38
:
15.915
[main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean
'lifecycleProcessor'
11
:
38
:
15.917
[main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching
for
key
'spring.liveBeansView.mbeanDomain'
in [systemProperties]
11
:
38
:
15.917
[main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Found key
'spring.liveBeansView.mbeanDomain'
in [systemProperties] with type [String] and value
''
11
:
38
:
15.919
[main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean
'helloWorld'
Welcome to the Spring world
生命周期信息
ApplicationContextAware:实现setApplicationContext方法。 BeanNameAware:实现setBeanName方法。 InitializingBean:实现InitializingBean方法。 BeanFactoryAware:实现setBeanFactory方法。 BeanPostProcessor:实现postProcessBeforeInitialization和postProcessAfterInitialization方法。 DisposableBean:实现destroy方法。
在HelloWorld类中添加如下方法:
1
2
3
4
5
6
7
public
void
myInit() {
System.out.println(
"custom myInit is called "
);
}
public
void
myDestroy() {
System.out.println(
"custom myDestroy is called "
);
}
修改xml文件:
1
2
3
4
5
<
bean
id
=
"helloWorld"
class
=
"com.packt.lifecycle.HelloWorld"
init-method
=
"myInit"
destroy-method
=
"myDestroy"
>
<
property
name
=
"message"
value
=
"Welcome to the Spring world"
>
</
property
>
</
bean
>
修改HelloWorldExample类
1
2
3
4
5
6
7
public
static
void
main(String[] args) {
AbstractApplicationContext context =
new
ClassPathXmlApplicationContext(
"applicationContext.xml"
);
HelloWorld world = (HelloWorld) context.getBean(
"helloWorld"
);
context.getBean(
"helloWorld"
);
System.out.println(world.getMessage());
context.registerShutdownHook();
}
现在执行可以看到“custom myInit is called ”等信息。
autowiring和注解
Spring容器可以自动处理bean之间的依赖关系,这样就没必要使用 <constructor-arg>和 <constructor-arg>标签,简化了应用程序上下文XML配置。 autowiring的类型如下: •no:默认没有。 •byName:使用配置文件中相同名字的beans定义。 •byType的:使用配置文件中相同属性的beans定义。如果有多个则抛出异常。 •constructor:类似type,但基于构造类型。 •default:先使用constructor,不成功则基于byType。
修改applicationContext.xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<beans xmlns=
"http://www.springframework.org/schema/beans"
xmlns:context=
"http://www.springframework.org/schema/context"
xmlns:aop=
"http://www.springframework.org/schema/aop"
xmlns:tx=
"http://www.springframework.org/schema/tx"
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.xsd
http:
//www.springframework.org/schema/context
http:
//www.springframework.org/schema/context/spring-context-4.1.xsd
http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http:
//www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
">
<context:annotation-config/>
<bean name=
"message"
id=
"message"
class
=
"java.lang.String"
>
<constructor-arg value=
"auto wired"
/>
</bean>
<bean id=
"helloWorld"
class
=
"com.example.HelloWorld"
>
</bean>
</beans>
注解类型如下: •@Required:该注释适用于bean的setter方法 •@Autowired:bean的setter方法,构造函数和属性 •@Qualifier:和@Autowired一起用于限定bean。 通过<context:annotation-config/>开启autowiring的注解。
修改HelloWorld:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package
com.example;
import
org.springframework.beans.BeansException;
import
org.springframework.beans.factory.BeanFactory;
import
org.springframework.beans.factory.BeanFactoryAware;
import
org.springframework.beans.factory.BeanNameAware;
import
org.springframework.beans.factory.DisposableBean;
import
org.springframework.beans.factory.InitializingBean;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.beans.factory.config.BeanPostProcessor;
import
org.springframework.context.ApplicationContext;
import
org.springframework.context.ApplicationContextAware;
public
class
HelloWorld
implements
ApplicationContextAware,BeanNameAware, InitializingBean,
BeanFactoryAware,BeanPostProcessor, DisposableBean {
@Autowired
private
String message;
public
String getMessage() {
return
message;
}
@Autowired
public
void
setMessage(String message) {
this
.message = message;
}
public
void
setBeanName(String arg0) {
System.out.println(
"setBeanName is called with "
+ arg0);
}
@Override
public
void
afterPropertiesSet()
throws
Exception {
System.out.println(
"afterPropertiesSet is called "
);
}
@Override
public
void
setBeanFactory(BeanFactory arg0)
throws
BeansException {
System.out.println(
"setBeanFactory is called "
);
}
public
void
myInit() {
System.out.println(
"custom myInit is called "
);
}
public
void
myDestroy() {
System.out.println(
"custom myDestroy is called "
);
}
@Override
public
void
destroy()
throws
Exception {
System.out.println(
"destroy is called "
);
// TODO Auto-generated method stub
}
@Override
public
Object postProcessAfterInitialization(Object arg0, String arg1)
throws
BeansException {
System.out.println(
"postProcessAfterInitialization is called with "
+arg0+
" and "
+arg1);
return
null
;
}
@Override
public
Object postProcessBeforeInitialization(Object arg0, String arg1)
throws
BeansException {
System.out.println(
"postProcessBeforeInitialization is called with "
+arg0+
" and "
+arg1);
return
null
;
}
@Override
public
void
setApplicationContext(ApplicationContext arg0)
throws
BeansException {
System.out.println(
"setApplicationContext is called "
);
}
}
现在执行可以看到”auto wired”信息。
aspect
AOP是Spring框架的关键组件之一。面向对象编程不能很好地处理一些通用功能。比如: •日志记录和跟踪 •事务管理 •安全 •缓存 •错误处理 •性能监控 •自定义业务规则 •事件处理
AOP覆盖OOP的数据驱动层,用AspectJ和Spring AOP的实现: •AspectJ:这是原来的AOP技术(从第一个版本的日期1995开始),提供了全面的,面向方向的编程语言,使用字节码修改。 •Spring AOP的:基于Java的AOP框架,它使用动态代理,主要用来解决企业级问题。
•Join point连接点:插入逻辑的连接点。通常在: °方法调用 °类初始化 °对象初始化 •Advice建议:连接点执行的代码。3种如下: °before。 °after。 °around(兼具before和after的功能。 •Pointcut切入点:连接点的集合,通常是多个实际Join point的执行点。 •Aspect切面:实现横切,连接advice和Pointcut。一个应用可以有 任何数目的方面的,根据不同的要求。 •Weaving编织:应用到代码的过程,有三种类型: °编译时 °类加载 °运行时
•目标: •简介:修改该结构,引入额外的方法或字段。
有两种类型的AOP: •静态AOP °weaving是构建过程中的另一个步骤 °例如Java程序,可以过改变和修改应用程序的实际字节码 •动态AOP °weaving在运行时动态地进行 °很容易改变的weaving过程而无需重新编译 Spring AOP是基于代理。关于代理的更多资料: http://en.wikipedia.org/wiki/Proxy_pattern,下面我们做个简单的演示:
创建接口IMessageWriter:
1
2
3
4
package
com.example;
public
interface
IMessageWriter {
void
writeMessage();
}
MessageWriter类实现IMessageWriter:
1
2
3
4
5
6
7
8
package
com.example;
public
class
MessageWriter
implements
IMessageWriter {
@Override
public
void
writeMessage() {
System.out.print(
"World"
);
}
}
调用 writeMessage()是连接点。我们想把“World”把改成“ Hello World !”。MethodInterceptor是AOP标准接口。新建类MessageDecorator:
1
2
3
4
5
6
7
8
9
10
11
package
com.example;
import
org.aopalliance.intercept.MethodInterceptor;
import
org.aopalliance.intercept.MethodInvocation;
public
class
MessageDecorator
implements
MethodInterceptor {
public
Object invoke(MethodInvocation invocation)
throws
Throwable {
System.out.print(
"Hello "
);
Object retVal = invocation.proceed();
System.out.println(
"!"
);
return
retVal;
}
}
AOPTest类使用ProxyFactory类创建代理:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package
com.example;
import
org.springframework.aop.framework.ProxyFactory;
public
class
AOPTest {
public
static
void
main(String[] args) {
MessageWriter target =
new
MessageWriter();
// create the proxy
ProxyFactory pf =
new
ProxyFactory();
// Add the given AOP Alliance advice to the tail
// of the advice (interceptor) chain
pf.addAdvice(
new
MessageDecorator());
// Set the given object as target
pf.setTarget(target);
// Create a new proxy according to the
// settings in this factory
MessageWriter proxy = (MessageWriter) pf.getProxy();
// write the messages
target.writeMessage();
System.out.println(
""
);
// use the proxy
proxy.writeMessage();
}
}
Spring JDBC
Spring Data Access Object (DAO)支持统一的方式访问JDBC, Hibernate或JDO。Spring还可以处理异常,转换为未检查或者运行时。 DAO支持类如下: • JdbcDaoSupport • HibernateDaoSupport • JdoDaoSupport • JpaDaoSupport
通常的JDBC访问数据库代码如下: 1.定义连接参数。 2.打开连接。 3.指定的语句。 4.准备和执行该语句。 5.设置循环遍历结果(如果有的话)。 6.处理每个迭代。 7.处理异常。 8.处理事务。 9.关闭连接。
Spring简化为如下: 1.指定语句。 2.处理每个迭代。
Spring-JDBC事务框架包含如下包: • org.springframework.jdbc.core • org.springframework.jdbc.datasource • org.springframework.jdbc.object • org.springframework.jdbc.support
org.springframework.jdbc.core包含如下类: • JdbcTemplate • 不同的回调接口 • 其他相关类
org.springframework.jdbc.datasource包有以下类: •便于数据源访问的工具类 •各种简单的DataSource实现,用于在J2EE容器之外测试和运行未修改的JDBC代码 •utility类提供静态方法从JNDI获得连接和必要时关闭连接。 •支持绑定线程的连接,例如DataSourceTransactionManager
org.springframework.jdbc.object包含以下内容: •线程安全并可重用的数据库查询,更新和存储过程类 •这种方法是通过JDO模型,查询对象与数据库断开连接 •JDBC的高层抽象依赖于底层抽象org.springframework.jdbc.core。
该org.springframework.jdbc.support包包含以下内容: •SQLException的转换功能和一些工具类 •转换异常 •使用Spring JDBC抽象层的代码不需要实现JDBC-或者RDBMS特定的错误处理 •所有unchecked异常。
JdbcTemplate类是org.springframework.jdbc.core的主类。它处理了资源创建和释放,简化了JDBC的使用。这有助于避免通用错误,如不关闭连接。它执行核心JDBC工作流,如语句创建和执行。
TestContext框架介绍
Spring的TestContext框架是一个通用的,注解驱动的框架,用于单元测试和集成测试。框架的资源位于org.springframework.test.context包,约定优于配置,每个配置都有默认值,通过注解可以修改非约定的配置。支持JUnit和TestNG,比如可以自定义JUnit执行器来支持非入侵的POJO测试类。
框架包含的类如下: •TestContext: 该类提供在测试执行的上下文和上下文管理和缓存支持。加载应用程序上下文使用ContextLoader或SmartContextLoader接口。 •TestContextManager:框架的主入口点。它管理单个TestContext类和发布事件到TestExecutionListener实现。
这是测试执行要点: °在静态类方法之前, °在测试执行方法之前, °在测试实例的准备 °测试执行方法之后 °在静态类方法之后
以下是接口: •TestExecutionListener •ContextLoader:这个接口加载集成测试的ApplicationContext •SmartContextLoader:扩展ContextLoader接口,在Spring3.1引入,处理资源位置,注解类,或上下文初始化,还可以设置 active bean profiles ( @ActiveProfiles )和属性资源。
每个测试有一个TestContextManager类,它管理TestContext并处理 dependency injection, dirty checks, transactional support等。TestContextManager委派TestExecutionListener(通过dependency injection,managing transactions实现实际的测试执行)。
默认TestExecutionListener的实现方式注册方式如下: • ServletTestExecutionListener: WebApplicationContext的Servlet API mock。 • DependencyInjectionTestExecutionListener • DirtiesContextTestExecutionListener:检查上下文,确实测试执行时是否有脏bean。它还处理@DirtiesContext注解。 • TransactionalTestExecutionListener:这提供了事务性支持 •SqlScriptsTestExecutionListener:通过@sql注解执行SQL脚本
自定义TestExecutionListener
新建Spring maven新工程SpringTests。
新建类SpringTestsApplication:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package
com.example;
import
org.springframework.context.ApplicationContext;
import
org.springframework.test.context.TestContext;
import
org.springframework.test.context.TestExecutionListener;
public
class
SysOutTestExecutionListener
implements
TestExecutionListener {
@Override
public
void
afterTestClass(TestContext testContext)
throws
Exception {
ApplicationContext ctx = testContext.getApplicationContext();
System.out.println(
"In afterTestClass for class = "
+ testContext.getTestClass());
}
@Override
public
void
afterTestMethod(TestContext testContext)
throws
Exception {
System.out.println(
"In afterTestMethod for = "
+ testContext.getTestMethod().getName());
}
@Override
public
void
beforeTestClass(TestContext testContext)
throws
Exception {
System.out.println(
"In beforeTestClass for class = "
+ testContext.getTestClass());
}
@Override
public
void
beforeTestMethod(TestContext testContext)
throws
Exception {
System.out.println(
"In beforeTestMethod for ="
+ testContext.getTestMethod().getName());
}
@Override
public
void
prepareTestInstance(TestContext testContext)
throws
Exception {
System.out.println(
"In prepareTestInstance for= "
+ testContext.getTestInstance());
}
}
新建类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package
com.example;
import
org.junit.Test;
import
org.junit.runner.RunWith;
import
org.springframework.test.context.ContextConfiguration;
import
org.springframework.test.context.TestExecutionListeners;
import
org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith
(SpringJUnit4ClassRunner.
class
)
@ContextConfiguration
(locations=
"classpath:applicationContext.xml"
)
@TestExecutionListeners
({SysOutTestExecutionListener.
class
})
public
class
TestExecutionListenerTest {
@Test
public
void
someTest()
throws
Exception {
System.out.println(
"executing someTest"
);
}
@Test
public
void
someOtherTest()
throws
Exception {
System.out.println(
"executing someOtherTest"
);
}
}
新建文件:SpringTests/src/main/resources/applicationContext.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
beans
xmlns
=
"http://www.springframework.org/schema/beans"
xmlns:context
=
"http://www.springframework.org/schema/context"
xmlns:aop
=
"http://www.springframework.org/schema/aop"
xmlns:tx
=
"http://www.springframework.org/schema/tx"
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
">
</
beans
>
配置Spring profile
Spring3.1引入了profile。它可以把一个包可以部署在各种环境中,如开dev, test, prod, perf等。 定义的系统属性spring.profiles.active,或使用 @ActiveProfiles注解测试类即可。
修改: applicationContext.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<
beans
xmlns
=
"http://www.springframework.org/schema/beans"
xmlns:xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:context
=
"http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<
bean
name
=
"noProfileBean"
id
=
"message"
class
=
"java.lang.String"
>
<
constructor-arg
value
=
"I'm a free bean"
/>
</
bean
>
<
beans
profile
=
"dev"
>
<
bean
name
=
"message"
id
=
"message"
class
=
"java.lang.String"
>
<
constructor-arg
value
=
"I'm a dev bean"
/>
</
bean
>
</
beans
>
<
beans
profile
=
"prod"
>
<
bean
name
=
"message"
id
=
"message"
class
=
"java.lang.String"
>
<
constructor-arg
value
=
"I'm a prod bean"
/>
</
bean
>
</
beans
>
</
beans
>
新建测试类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package
com.example;
import
static
org.junit.Assert.*;
import
org.junit.Test;
import
org.junit.runner.RunWith;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.context.ApplicationContext;
import
org.springframework.test.context.ActiveProfiles;
import
org.springframework.test.context.ContextConfiguration;
import
org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith
(SpringJUnit4ClassRunner.
class
)
@ContextConfiguration
(locations=
"classpath:applicationContext.xml"
)
@ActiveProfiles
(profiles={
"dev"
})
public
class
ProfileTest {
@Autowired
ApplicationContext context;
@Test
public
void
profile()
throws
Exception {
assertEquals(
"I'm a dev bean"
, context.getBean(
"message"
));
//assertEquals("I'm a free bean", context.getBean("noProfileBean"));
}
}
除了ActiveProfiles注解,也可以在环境变量中指定。比如spring.profiles.active = dev。
环境mock
后面补充
JNDI查找mock
后面补充
ReflectionTestUtils
org.springframework.test.util包的ReflectionTestUtils类包含不少反射方法,如设置非公开域或调用private/protected的setter方法等。 如下: •ORM框架,如JPA和Hibernate •Spring的注解支持,如@Autowired,@Inject,和@Resource,这对于private/protected域的提供依赖注入,setter方法和配置方法。
下面的示例演示ReflectionUtils的功能: 新增方法:Secret
1
2
3
4
5
6
7
8
9
package
com.example;
public
class
Secret {
private
String secret;
public
void
initiate(String key) {
this
.secret = key.replaceAll(
"a"
,
"z"
).replaceAll(
"i"
,
"k"
);
}
}
测试代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package
com.example;
import
static
org.junit.Assert.*;
import
java.lang.reflect.Field;
import
org.junit.Test;
import
org.springframework.util.ReflectionUtils;
public
class
ReflectionUtilsTest {
@Test
public
void
private_field_access()
throws
Exception {
Secret myClass =
new
Secret();
myClass.initiate(
"aio"
);
Field secretField = ReflectionUtils.findField(Secret.
class
,
"secret"
, String.
class
);
assertNotNull(secretField);
ReflectionUtils.makeAccessible(secretField);
assertEquals(
"zko"
, ReflectionUtils.getField(secretField, myClass));
ReflectionUtils.setField(secretField, myClass,
"cool"
);
assertEquals(
"cool"
, ReflectionUtils.getField(secretField, myClass));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public
interface
MyInterface {
// constant definition
String URL =
"http://www.vogella.com"
;
// public abstract methods
void
test();
void
write(String s);
// default method
default
String reserveString(String s){
return
new
StringBuilder(s).reverse().toString();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public
class
MyClassImpl
implements
MyInterface {
@Override
public
void
test() {
}
@Override
public
void
write(String s) {
}
public
static
void
main(String[] args) {
MyClassImpl impl =
new
MyClassImpl();
System.out.println(impl.reserveString(
"Lars Vogel"
));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
public
interface
A {
default
void
m() {}
}
public
interface
B {
default
void
m() {}
}
public
class
C
implements
A, B {
@Override
public
void
m() {}
}
1
2
3
4
public
class
C
implements
A, B {
@Override
public
void
m() {A.
super
.m();}
}