一、Bean的作用域
Spring在初始化一个Bean实例时,可以同时为其指定特定的作用域。作用域将会对Bean的生命周期和创建方式产生影响。
Bean的作用域类型:
Singleton作用域是Spring容器默认的作用域,当一个Bean的作用域为Singleton时,Spring容器中只会存在一个共享的Bean实例。并且对于所有的Bean请求,只要id与该bean定义的ID属性值相匹配,就会返回bean的同一个实例。单例模式对于无会话状态的Bean,如Dao、Service,是理想的选择。
spring默认就是Singleton模式。
我们查看Spring的配置文件,里面定义了bean id和对应的class实现类,同时指定了scope。
接下来在包中创建一个名为Hello的类,里面不写任何方法(默认会创建一个无参构造函数)。
接下来写一个测试类,里面两次获取bean对象并打印,如下所示:
运行测试类,查看输出结果,得到的对象名称相同,说明Spring容器只创建一个Hello类的实例。其实,不写scope=singleton,默认也只创建一个实例,这是Spring的默认配置。
对于想保持会话状态的bean,应该使用prototype作用域。在这种模式下,Spring会为每个对该Bean的请求都创建一个实例。
我们将上面实例中的scope修改成prototype,再看输出,会发现两次打印的不同,说明创建了两个不同的Bean实例。
二、Bean的生命周期
Sping对singleton和prototype的生命周期管理是不一样的。
对singleton作用域下的bean生命周期,进行全生命周期管理。
对于prototype作用域下的bean生命周期管理,只负责创建。创建后,Spring容器将不再跟踪其生命周期。
Bean的生命周期管理如下所示:
上图一共展现了12步,解释如下所示:
三、Bean的装配方式(依赖注入方式)
Bean的装配方式有三种:
1.基于XML的装配
2.基于Annotation方式
3.自动装配
1.基于XML的装配
在XML的装配模式下,又分为:
1.1 设值注入(Setter Injection),Bean必须满足:
Bean类必须提供一个默认的构造方法
Bean类必须为需要注入的属性提供对应的setter方法。
1.2 构造注入(Constructor Injection)
在Spring的配置文件中,使用元素的子元素元素为每个属性注入值。
在真实的使用中,1.1和1.2往往结合使用。
为了方便理解,我们看一段代码。
如下图所示,我们创建了一个User类,里面包含了Username和Password的设置值和获取值的方法:
下图中,定义了一个有参构造方法,传入的参数是username和password。
下图中@Override后面的代码,作用是当测试类调用User类时,打印username和password的内容:
接下来,我们再看一下Spring的配置文件:bean5.xml。我们看到包含两部分内容:
第一部分是通过构造方式装配user实例,同时进行了赋值,bean id是user1
第二部分是使用Set方式装配user实例,这段也进行了赋值,但我们看到和第一部分内容不同,bean id是user2:
书写一个测试类。我们看到测试类先通过应用上下文加载xml文件,然后获取user1和user2的实例,并进行打印:
2.基于Annotation的装配
Spring可以使用XML实现Bean的装配工作,但如果bean太多,XML文件就会比较臃肿。JDK1.5开始,提供了annotation功能,Spring也全面支持。常见的注解如下:
接下来我们看代码:
首先创建一个接口,名为UserDao
接下来创建一个接口实现类,名为UserDaoImpl。
我们看到上图中第三行有@Repositiory(“userDao”),这是将UserDaoImpl这个类标示为Spring中的Bean,这行代码的作用,相当于在XML中这样写:
接下来,创建一个名为UserService的接口:
接下来,创建UserService的接口的实现类:UserServiceImpl。
下图中第4行相当于XML中:
<bean id="userService" class="cn.itcast.annotation.UserServiceImpl"/>
下图中第6行相当于配置文件中:
。
类的最后,调用了userDao中的save()方法。
接下来,创建UserAction类。
下图第四行使用@Controler注解标注UserAction类相当于XML中:
serAction" class="cn.itcast.annotation.UserAction"/
下图第六行相当于:
userService"/>。
【ref的作用是:property、contructor-arg等元素的子元素,该元素中的bean属性用于指定Bean工厂中某个Bean实例的引用】
最后调用了userService的save()方法:
接下来,创建beans6.xml.
配置文件的作用是启动compont scan,并且是在cn.itcast.annotation目录下扫描(我们之前创建的几个bean都在这个目录下):
接下来,创建测试类:
我们看到测试类会先加载beans6.xml。
第15行获取UserAction的实例:userAction。
上图第18行是输出userAction的实例;
上图第19行是调用userAction中的save()方法---->调用userservice中的save()方法--->调用userdao中的save()方法--->打印:"userdao...save..."
然后,每个类还有自己的打印内容,因此最终的打印内容是:
3.自动装配
自动装配是:将一个Bean注入到其他Bean的Property中。这需要使用到元素的autowire属性,它的五个值是:
我们基于上一小节是示例,改造配置文件:
上图中即通过autowire="byName"的字段,实现通过bean id名自动装配。
使用这种方式后,实际上面UserServiceImpl、UserAction两个类中的源码中,实现ref部分的代码就可以删除了,如:
参考文献:
《SSH框架整合实战教程》-清华大学出版社