接上一篇:使用Maven配置spring
1.用到的依赖包
Pom.xml添加:
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>3.0.0.RELEASEversion>
<type>jartype>
<scope>compilescope>
dependency>
<dependency>
<type>jartype>
<scope>testscope>
dependency>
注:junit从上回的3换到了4.10
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:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">
beans>
注释掉原来的,加入类(红色部分,不加也行)和要扫描的包(下面讲到)。
package com.syz.test01;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Service("app")
@Scope("singleton")
public class App{
@Autowired
@Qualifier("person")
public Person person;
public Person getPerson() {
return person;
}
@PostConstruct
public void init(){
System.out.println("app 在初始化!");
}
@PreDestroy
public void destory(){
System.out.println("app 被销毁!");
}
}
@Service("app")
要点1:用于注解类,表示该类会被spring扫描到
要点2:这几个用法功能一致
@Controller (控制层)
Indicates that an annotated class is a "Controller" (e.g. a web controller).
This annotation serves as a specialization of @Component, allowing for implementation classes to be autodetected through classpath scanning. It is typically used in combination with annotated handler methods based on the RequestMapping annotation.
@Repository (持久层)
Indicates that an annotated class is a "Repository" (or "DAO").
A class thus annotated is eligible for Spring DataAccessException translation. The annotated class is also clarified as to its role in the overall application architecture for the purpose of tools, aspects, etc.
As of Spring 2.5, this annotation also serves as a specialization of @Component, allowing for implementation classes to be autodetected through classpath scanning.
@Service (业务层)
Indicates that an annotated class is a "Service" (e.g. a business service facade).
This annotation serves as a specialization of @Component, allowing for implementation classes to be autodetected through classpath scanning.
@Component (组件)
这 3 个注释分别和持久层、业务层和控制层(Web 层)相对应。虽然目前这 3 个注释和 @Component 相比没有什么新意,但 Spring 将在以后的版本中为它们添加特殊的功能。所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用 @Repository、@Service 和 @Controller 对分层中的类进行注释,而用 @Component 对那些比较中立的类进行注释。
要点3:scope
表示该bean的作用域,
@Scope("singleton")
"singleton" and "prototype"
默认单例模式
要点4:
@PostConstruct 定义该bean初始化前执行的函数
@PreDestroy 定义该bean销毁前执行的函数
该两个注解以及接下来的@Resource不是spring的, 是java ee自带的。
要点5:注入
@Autowired
@Retention(value=RUNTIME)
@Target(value={CONSTRUCTOR,FIELD,METHOD})
public @interface Autowired
@Autowired是Spring 提供的,需导入
Package:org.springframework.beans.factory.annotation.Autowired;
只按照byType 注入。一个参数 required,Boolean 是否必须
@Resource
@Resource(name="12",type=App.class)(两个比较重要的参数)
@Resource默认按 byName 自动注入,是J2EE提供的, 需导入Package:
javax.annotation.Resource;
@Resource有两个中重要的属性:name和type ,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用 byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
@Resource装配顺序
(1). 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常;
(2). 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常;
(3). 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常;
(4). 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入。
Qualifier
使用 @Qualifier 注释指定注入 Bean 的名称
一般使用方法
@Autowired
@Qualifier("person")
或者@Qualifier("person")
或者@Resource(name="app",type=App.class)
目录结构
在上次的基础上,创建src/test/resources源文件夹
applicationContext-test.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:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"
default-lazy-init="true">
<context:component-scan base-package="com.syz.test01" />
beans>
只需配置要扫描的包就行了
log4j.properties:
# Output pattern : date [thread] priority category - message
log4j.rootLogger=debug,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
log4j.logger.org.springframework.beans.factory.annotation=debug,stdout
log4j.appender.F = org.apache.log4j.DailyRollingFileAppender
log4j.appender.F.file=d:\\login.log
log4j.appender.F.DatePattern='.'yyyy-MM-dd
log4j.appender.F.layout=org.apache.log4j.PatternLayout
log4j.appender.F.layout.ConversionPattern= %5r %-5p %c{2} - %m%n
日志输出的配置,看个人喜好
测试类:
package com.syz.test01;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
@ContextConfiguration(locations = { "/applicationContext-test.xml" })
public class AppTest extends AbstractJUnit4SpringContextTests{
@Autowired
@Qualifier("app")
public App app ;
public App getApp() {
return app;
}
public void setApp(App app) {
this.app = app;
}
@Test
public void testApp(){
System.out.println(app.getPerson().getName());
System.out.println(app.getPerson().getAge());
}
}
说明:给测试类注入了app,app里又注入了person,在该测试类中,就能拿到app中的person对象,并打印出来。
Person.java
package com.syz.test01;
import org.springframework.stereotype.Component;
@Component
public class Person {
public String name = "zhangsan";
public String age = "1";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
预计的效果是控制台能打印出person里的默认属性。
说明1:junit4.10不是所有版本的spring-test都能搭配的,如果运行报错,看下junit和spring-test的搭配问题
说明2:spring的注入注解方式