今天学习spring的bean组件装载功能,个人不太喜欢xml文件一个个配置bean的方式,所以主要学习测试注解式的自动装载方式。下面将简单说明下@Component的用法,简单入门示例献给大家。
实现主要步骤说明:
1、ApplicationContext.xml(spring上下文环境配置)文件先配置好需要自动扫描的包位置。注册完成后,在spring初始化上下文环境时,会自动扫描声明的包以及子包下面有注解(@Component,@Repository,@Service,@Controller)的类型,并缓存起来。这里需要提一下@Component是一个基础的注解,不对代码功能分类进行区分,@Repository一般用于业务逻辑层的类注解,@Service用于dao层注解,@Controller用于控制器注解。
<?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" 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.xsd">
<!-- 定义 bean 的 id,以及对应的 java 类 -->
<context:component-scan base-package="com.spring.simm" use-default-filters="true"/>
<!--<bean id="helloWorld" class="com.spring.simm.impls.HelloWorld"> <property name="message" value="Hello World!" /> </bean>-->
</beans>
2、添加一个HelloWorld组件。需要注意的是@Component注解的组件,默认都是单例模式,即缺省的@Scope("singleton")。通过spring去getBean实例时,其实都是同一个对象。我这里将改组件设置成多例模式,即添加注解@Scope("prototype")。
@Scope的模式有:singleton、prototype、request、session、global session,其他模式各位可以查阅网上资料
public interface IHelloWorld { void say(String name); }
@Scope("prototype") //@Scope("singleton")
@Component("hello") public class HelloWorld implements IHelloWorld { private static int no = 0; public HelloWorld(){ no++; System.out.println("IHelloWorld[" + no +"]运行"); } /** * 说话 */
public void say(String name) { // TODO Auto-generated method stub
System.out.println(name +" : hello world!"); } }
3、再添加一个HelloWorldService组件,注解成@Service,单例模式(后面,我们针对单例、多例两个组件的表现进行测试)。在服务内声明了一个自动装载的HelloWorld组件(@AutoWired),通过getHelloWorld方法返回,由于服务类是单例模式,因此这个helloworld对象也是唯一的,在服务的整个生命周期中不变。getHelloWorld2方法则每次都创建一个新的HelloWorld对象。
public interface IHelloWorldService { HelloWorld getHelloWorld(); HelloWorld getHelloWorld2(); }
/** * Hello world 服务,默认情况下就是单例的 * @author wh-simm * */ @Service("helloservice") public class HelloWorldService implements IHelloWorldService { private static int no = 0; public HelloWorldService(){ no++; System.out.println("HelloWorldService["+no+"]启动"); } /** * 自动装载 */ @Autowired private HelloWorld helloWorld; /** * 获取自动装载的实例 */
public HelloWorld getHelloWorld(){ return helloWorld; } /** * 新建实例 */
public HelloWorld getHelloWorld2(){ return new HelloWorld(); } }
4、添加测试代码
public class app { public static void main(String[] args) { // 获取 classpath 中的 Beans.xml 到上下文 context //1.装载spring上下文配置文件,完成spring容器的初始化
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); //2.从spring容器中获取bean-helloworld 实例1
IHelloWorld obj1 = (IHelloWorld) context.getBean("hello"); obj1.say("simm1"); //3.从spring容器中获取bean-helloworld 实例2
IHelloWorld obj2 = (IHelloWorld) context.getBean("hello"); obj2.say("simm2"); //3.从spring容器中获取bean-HelloWorldService 实例1(单例)
IHelloWorldService service = (IHelloWorldService)context.getBean("helloservice"); service.getHelloWorld().say("simm3"); service.getHelloWorld().say("simm4"); //3.从spring容器中获取bean-HelloWorldService 实例2(单例)
IHelloWorldService service2 = (IHelloWorldService)context.getBean("helloservice"); service2.getHelloWorld2().say("simm5"); service2.getHelloWorld2().say("simm6"); // 关闭上下文,防止内存泄漏
((ClassPathXmlApplicationContext) context).close(); } }
5、测试结果显示,从spring容器中两次获取HelloWorldService服务,确实只运行了一次,说明默认情况下Component确实是单例的,而HelloWorld组件每次获取都是创建新的对象,属于多例模式。服务中自动装载的HelloWorld组件(@AutoWired)在单例的组件中使用时,要考虑清楚对象的生命周期。
参考资料
https://www.cnblogs.com/lonecloud/p/5745902.html
http://blog.csdn.net/qiuhan/article/details/45581371