之前写过的那篇Spring之依赖注入中Spring是通过beans.xml文件管理Bean的实例化以及相应参数的传入,今天,我们讲述的则是使用在Java类中使用注释从而对各Bean类进行管理,从而减轻beans.xml文件的工作量,毕竟学习xml知识也不是一蹴而就的事情啊。所以这里介绍一下注释来实现功能的,有兴趣的朋友可以瞧一瞧,如果能够提出指导意见那就更好啦。
如果不使用配置文件来配置Bean实例,而是希望Spring会自动搜索某些路径下的Java类,并将这些Java类注册成Bean实例。而在类中用注释标注Bean类,常用的有如下几个标注:
@Component:标注一个普通的Spring Bean类
@Controller:标注一个控制器组件类
@Service:标注一个业务逻辑组件类
@Repository:标注一个DAO组件类
本文的示例主要都是普通类,所以用@Component标注。另外如果一个Bean实例需要注入另一个Bean实例,则需要使用@Resource来注释,@Resource有一个name属性,Spring用这个值标记需要被注入的Bean实例的id,其实@Resource与<property.../>元素的ref属性有异曲同工之妙。之后Spring4.0的自动装配@Autowired可以实现同样的功能。
另外,1.如果要指定Bean的作用域,则用@Scope修饰Bean类,默认是singleton,也可将value值定为"prototype"。2.若要定制生命周期行为,则可使用@PostConstruct和@PreDestroy来修饰,前者修饰Bean的初始化方法,后者修饰的方法是Bean销毁之前的方法。3.@DependsOn({})修饰Bean类,则会在Bean类实例化之前,强制实例化指定的类。4.@Lazy(true)修饰类则表示不会预初始化Bean类。
以上是注释基本的几个知识点,以下通过实例进行讲述。
首先是相应的接口Person和Axe接口:
package handle;
public interface Person {
public void useAxe();
}
package handle;
public interface Axe
{
public String chop();
}
相应的实现类:
package handle.impl;
import org.springframework.stereotype.*;
import handle.*;
import javax.annotation.*;
@Component
public class Chinese implements Person
{
// 执行Field注入
@Resource(name="steelAxe")
private Axe axe;
// 实现Person接口的useAxe()方法
public void useAxe()
{
// 调用axe的chop()方法,
// 表明Person对象依赖于axe对象
System.out.println(axe.chop());
}
@PostConstruct
public void init()
{
System.out.println("正在执行初始化的init方法...");
}
@PreDestroy
public void close()
{
System.out.println("正在执行销毁之前的close方法...");
}
}
package handle.impl;
import handle.Axe;
import org.springframework.stereotype.*;
@Component
public class SteelAxe implements Axe {
@Override
public String chop()
{
return "钢斧砍柴真快";
}
}
由上面两个实现类可以看出,用到了之前讲到的几个注释内容。接下来需要配置beans.xml,而这个配置比较简单,只需要配置Spring容器自动扫描某个包即可,
<?xml version="1.0" encoding="GBK"?>
<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-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 自动扫描指定包及其子包下的所有Bean类 -->
<context:component-scan
base-package="handle"/>
</beans>
该实例的beans.xml文件通过<context:component-scan..../>指定了Spring容器自动扫描handle文件夹。接下来编写工具类进行测试:
package test;
import org.springframework.context.*;
import org.springframework.context.support.*;
import handle.*;
public class BeanTest
{
public static void main(String[] args)
{
// 创建Spring容器
AbstractApplicationContext ctx = new
ClassPathXmlApplicationContext("beans.xml");
// 注册关闭钩子
ctx.registerShutdownHook();
Person person = ctx.getBean("chinese" , Person.class);
person.useAxe();
}
}
运行程序,结果如下:
正在执行初始化的init方法...
钢斧砍柴真快
正在执行销毁之前的close方法...
结果证实了
@PostConstruct和@PreDestroy,前者修饰Bean的初始化方法,后者修饰的方法是Bean销毁之前的方法。并且使用了注释之后,配置中省去了大篇幅,节省了配置的压力,而是将Bean实例化等放在每个Java类中通过注释实现,体现了分而治之的思想。