本章写的主要是bean的三种初始化与注销方式及几个注解组件。
初始条件:
1. Java version : 1.8
2. maven version : 1.3.9
3. IDE: IDEA
第1步: 创建简单形式的 Maven 工程(quick starter)。
第2步:在 POM 文件中加入 Spring5 的依赖。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.0.RELEASE</version>
</dependency>
第3步: 创建 User 类作为 bean,加上 @Component 作为 Spring 的一个组件。
import org.springframework.stereotype.Component;
@Component
public class User {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
第4步: 创建主类 App (含有main的可执行程序),加上@ComponentScan,让 Spring 自动去扫描当前包及其子包里面带有 @Component @Configuration 等注解的类,并加载为组件(bean).
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
public class App
{
public static void main( String[] args )
{
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(App.class);
System.out.println(ctx.getBean(User.class));
System.out.println("User ID --- > " + ctx.getBean(User.class).getId());
ctx.close();
}
}
此时 User 类并没有初始化,运行程序输出的是:
com.test.User@58fdd99
User ID --- > null
bean 的初始化及销毁方式一
使 User 类继承 Spring 自带的初始化与销毁组件 InitializingBean(初始化),DisposableBean(销毁),并继承其方法。
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@Component
public class User implements InitializingBean,DisposableBean{
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
/* User bean 初始化操作 */
public void afterPropertiesSet() throws Exception {
System.out.println("<--------User bean 初始化-------->");
id = "ID_0000001";
}
/* User bean 销毁操作 */
public void destroy() throws Exception {
System.out.println("<--------User bean 销毁-------->");
}
}
在上面的初始化代码中,使 User.id 初始化为 id=“ID_0000001”,运行程序的结果是:
<--------User bean 初始化-------->
com.test.User@709ba3fb
User ID --- > ID_0000001
<--------User bean 销毁-------->
bean 的初始化及销毁方式二
只需要修改上面的 User 类,使用 @PostConstruct(初始化)
@PreDestroy (销毁)注解声明方法。
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class User {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
/* 初始化方法 */
@PostConstruct
public void init() throws Exception {
System.out.println("<--------User bean 初始化-------->");
id = "ID_0000001";
}
/* 销毁方法 */
@PreDestroy
public void destroy() throws Exception {
System.out.println("<--------User bean 销毁-------->");
}
}
运行主类 App 结果输出:
<--------User bean 初始化-------->
com.test.User@525b461a
User ID --- > ID_0000001
<--------User bean 销毁-------->
bean 的初始化及销毁方式三
- 修改 User 类:
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class User {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void init() throws Exception {
System.out.println("<--------User bean 初始化-------->");
id = "ID_0000001";
}
public void destroy() throws Exception {
System.out.println("<--------User bean 销毁-------->");
}
}
- 新建 UserConfig 配置类,在声明 bean 时指定 User 的初始化与销毁方法。
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfig {
@Qualifier("getUser")
@Bean(initMethod = "init",destroyMethod = "destroy")
public User getUser(){
return new User();
}
}
- 修改 App 主类:
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
public class App
{
public static void main( String[] args )
{
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(App.class);
System.out.println("UserConfig --- > " + ctx.getBean(UserConfig.class).getUser().getId());
System.out.println("User ID --- > " + ctx.getBean("getUser"));
ctx.close();
}
}
结果输出:
<--------User bean 初始化-------->
UserConfig --- > ID_0000001
User ID --- > com.test.User@145eaa29
<--------User bean 销毁-------->
@Component、@Repository、@Service、@Controller
的作用都是将类标识为 bean 。只是它们在应用时用在不同的地方,已做层次上的区分。
Component : 用于普通的类。
Repository : 用于 dao 层。
Service : 用于service 层。
Controller : 用于 Controller。
- Repository 示例:
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
}
- Service 示例:
import org.springframework.stereotype.Service;
@Service
public class UserService {
}
- Controller 示例:
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
}
注入bean,使用 Autowired / Resource(JSR-250) / Inject (JSR-330 ,需要额外添加javax.inject 依赖)
- 在 Controller 中 注入 Service :
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
@Autowired
private UserService userService;
}
- 在 Service 中 注入 Dao :
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserDao userDao;
}
可能存在的问题
Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.test.User' available: expected single matching bean but found 2: user,getUser
在注入 bean 的时候可能提示存在多个相同类型的bean,此时可以使用 @Primary 声明目标bean,这个注解的意思是,如果系统找到多个相同类型的bean,会首先来取有Primary 声明的bean,用来解决存在bean的注入失败问题。