Spring MVC学习指南:Beans
前面提到,Bean是可以通过xml(不推荐)、java配置类、注解,三种方式注册到容器中。
注意:默认的生命周期是Singleton。其含义是,在应用中,无论何时、何处,获取这个Bean的实例时,都是共享的同一个实例。因此,在使用Singleton的实例时,需要考虑线程安全的问题。因此,一般将无状态的类设计为Singleton类型。
在容器中,Bean都是通过id进行唯一标记的,在任何位置你都是可以通过指定的id或者Bean的名称获取这个Bean的实例的。但是id、名称并不是必须指定的,如果你不指定,Spring会自动为其生成一个名称。但是,一般为了便于对其进行引用,我们都会对其命名。
绑定的优先级:
1. 如果id或名称不存在,则优先根据类型进行绑定。
2. 如果你为其指定了@Primary,或者这个Bean是唯一的,则无需再指定名称。
Bean的定义
一般包含以下属性:
class | 全限定类名 |
id | 唯一标记 |
name | 为其指定的名称 |
parent | 父类 |
scope | 声明周期 |
constructorargs | 构造器参数 |
properties | 属性参数 |
autowire mode | 自动绑定 |
primary | 首选实现 |
depends-on | 依赖Bean的初始化 |
lazy-init | 懒加载。用到再初始化 |
init-method | 初始化方法 |
destory-method | 销毁方法 |
factory-method | 工厂方法 |
factory-bean | 与工厂方法配合使用,用于使用指定的工厂类生产Bean |
基于xml的示例:
<bean id="xmlTaskService" class="com...XmlDefinedTaskService"
init-method="init" destroy-method="cleanup">
<constructor-arg ref="userService"/>
<constructor-arg>
<bean class="com...TaskInMemoryDAO"></bean>
</constructor-arg>
</bean>
基于注解的示例:
@Service
public class AnnotatedTaskService implements TaskService {
...
@Autowired
private UserService userService;
@Autowired
private TaskDAO taskDAO;
@PostConstruct
public void init() {
logger.debug(this.getClass().getName() + " started!");
}
@PreDestroy
public void cleanup() {
logger.debug(this.getClass().getName() + " is about to destroy!");
}
public Task createTask(String name, int priority, int createdByuserId, int assigneeUserId) {
Task task = new Task(name, priority, "Open",
userService.findById(createdByuserId), null,
userService.findById(assigneeUserId));
taskDAO.createTask(task);
logger.info("Task created: " + task);
return task;
}
...
}
Bean的初始化
通过构造器创建Bean的实例:
<bean id="greeter" class="com...GreetingBean"></bean>
@Component("greeter")
public class GreetingService {
...
}
通过静态工厂方法实例化:
<bean id="Greeter" class="...GreetingBean" factory-method="newInstance"></bean>
@Configuration
@ComponentScan(basePackages = "com.springessentialsbook")
public class SpringJavaConfigurator {
...
@Bean
public BannerService createBanner() {
return new BannerServiceImpl();
}
...
}
xml通过factory-method指定,java配置类则直接通过@Bean注解的方法生产实例。
通过实例工厂方法实例化:
通过其他Bean的非静态方法生产实例。
<bean id="greeter" factory-bean="serviceFactory" factory-method="createGreeter"/>
<bean id="serviceFactory" class="...ServiceFactory">
<!— ... Dependencies ... -->
</bean>
Bean的注入
Spring支持构造器注入,set方法注入两种。
构造器注入:
我们SimpleTaskService需要用到UserService、TaskDAO的实例。
public class SimpleTaskService implements TaskService {
...
private UserService userService;
private TaskDAO taskDAO;
public SimpleTaskService(UserService userService, TaskDAO taskDAO) {
this.userService = userService;
this.taskDAO = taskDAO;
}
...
}
<bean id="taskService" class="com...SimpleTaskService"">
<constructor-arg ref="userService" />
<constructor-arg ref="taskDAO"/>
</bean>
对于简单类型的构造器参数,可以直接在xml中进行配置:
<bean id="systemSettings" class="com...SystemSettings">
<constructor-arg index="0" type="int" value="5"/>
<constructor-arg index="1" type="java.lang.String" value="dd/mm/yyyy"/>
<constructor-arg index="2" type="java.lang.String" value="Taskify!"/>
</bean>
起始的序号从0开始。
基于Setter方法的注入:
<bean id="systemSettings" class="com...SystemSettings">
<property name="openUserTasksMaxLimit" value="5"/>
<property name="systemDateFormat" value="dd/mm/yyyy"/>
<property name="appDisplayName" value="Taskify!"/>
</bean>
注入List
<bean id="systemSettings" class="com...SystemSettings">
. . .
<constructor-arg>
<list>
<value>[email protected]</value>
<value>[email protected]</value>
<value>[email protected]</value>
</list>
</constructor-arg>
</bean>
注入对象时,可以使用<ref>替换<value>
注入Map
<bean id="systemSettings" class="com...SystemSettings">
. . .
<property name="emails">
<map>
<entry key="admin" value="[email protected]"></entry>
<entry key="it" value="[email protected]"></entry>
<entry key="devops" value="[email protected]"></entry>
</map>
</property>
</bean>
注入对象时,可以使用<ref>或<bean>替换<value>
自动绑定注入
可以通过注解构造器方法:
@Service
public class AnnotatedTaskService implements TaskService {
...
@Autowired
public AnnotatedTaskService(UserService userService, TaskDAO taskDAO) {
this.userService = userService;
this.taskDAO = taskDAO;
}
...
}
可以注解成员变量:
@Service
public class AnnotatedTaskService implements TaskService {
...
@Autowired
private UserService userService;
@Autowired
private TaskDAO taskDAO;
...
}
区分不同的实现的注入:
对成员变量使用@Qualifier
@Autowired(required = true)
@Qualifier("taskDAO")
private UserService userService;
对构造器方法的参数:
@Autowired
public AnnotatedTaskService(@Qualifier("userService") UserService userService, @Qualifier("taskDAO") TaskDAO taskDAO) {
this.userService = userService;
this.taskDAO = taskDAO;
}
上一篇: mongdb
下一篇: PRML:二元变量分布
推荐阅读
-
Spring MVC框架配置方法详解
-
Spring MVC HelloWorld入门及运行机制 (一)
-
Spring MVC源码(三) ----- @RequestBody和@ResponseBody原理解析
-
你知道@RequestMapping的name属性有什么用吗?【享学Spring MVC】
-
关于Spring MVC在Controller层中注入request的坑详解
-
干货分享:ASP.NET CORE(C#)与Spring Boot MVC(JAVA)异曲同工的编程方式总结
-
基于Maven 的 Spring MVC
-
三、解决Spring MVC拦截器导致静态资源访问失败(基于java注解配置)
-
详解Spring mvc ant path的使用方法
-
Spring MVC之DispatcherServlet详解_动力节点Java学院整理