Spring中三种装配bean的方式:自动、Java代码及XML装配 您所在的位置:网站首页 装配bean的三种方式 Spring中三种装配bean的方式:自动、Java代码及XML装配

Spring中三种装配bean的方式:自动、Java代码及XML装配

2024-06-18 22:47| 来源: 网络整理| 查看: 265

推荐使用装配的顺序:自动装配》Java代码》XML装配

一,自动装配

1、Spring从两个角度实现自动化装配:

组件扫描(component scanning):Spring会自动发现应用上下文中所创建的bean。自动装配(auto wiring):Spring自动满足bean之间的依赖。 组件扫描和自动装配组合在一起就可以发挥强大的威力,它们能将你的显示配置降到最低。以光盘和播放器为例,具体看以下代码: //先定义一个CompactDisc 接口 public interface CompactDisc { //具体内容不重要 public void play(); } //定义一个CompactDisc实现类 @Component("popularMusic") public class PopularMusic implements CompactDisc { @Override public void play() { System.out.println("播放流行乐"); } } // //配置类 @Configuration @ComponentScan public class CDPlayerConfig { //什么都不用写 }

到目前为止,上述仅仅是一个孤零零的类,什么也没做。那么我们应该如何使用呢?我们有最一般的方法就是new一个对象出来,然后再调用该对象的play()方法即可。但是用new创建对象的方法在实际的业务代码中增加耦合,难以维护,因此才有了Spring。接下来看一下如何用自动装配的方式装配bean(和普通的Java类,Spring中的特殊称谓),继而使用bean的方法。

//单元测试 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = CDPlayerConfig.class) public class CDPlayerTest { @Autowired private CompactDisc cd; @Test public void test(){ cd.play(); } } //测试结果: 播放流行乐

看完所有代码会发现,上述代码和平时自己写的代码没啥区别,仅仅只多了几个注解(带@符号的),但就是这几个注解起到了作用。你自己并没手动创建一个CompactDisc 对象,而事实的确存在,而且成功运行,这一切都由Spring容器完成。 2、几个常用的注解: @Component: 注解用来说名该类作为一个组件类,并告知Spring要为该类创建bean @Configuration: 该注解用来说名该类是一个配置类 @ComponentScan: 启用Spring组件扫描(默认不启用),默认扫描与配置类在同一包带 有@ComPonent注解的类。有两个属性: (1)basePackages:用来设置要进行组件扫描的基础包,值为数组,数组属性为字符串 (2)basePackageClasses: 设置的数组中包含了类,这些类所在的包将作为组件扫描的基础包 @RunWith(SpringJUnit4ClassRunner.class):在测试之前自动生成Spring的应用上下文 @ContextConfiguration(classes = CDPlayerConfig.class):加载配置类。 所以上述代码大致的执行原理如下: 首先Spring容器首先加载配置类,根据配置类中的设置再去扫描指定包中的带有@Component的类;然后Spring容器生成扫描到的所有类的对象(默认是单例的),然后根据需要(哪里有@Autowired)自动装配所需要的bean,至于bean的生命周期则由Spring管理。

二、Java代码装配

要用Java代码来装配bean,那么配置类肯定也是少不了的,一个很简单的配置类定义如下:

@Configuration public class JavaConfig { }

这里和上面的配置类不同的地方是这里删除了@ComponentScan注解,因为该注解使用进行设置组件扫描的,而在这里的bean注入是通过Java代码配置的,因此不需要。如果删除之后,再去运行上述的CDPlayerTest的话会报BeanCreationException异常。因为测试期间需要注入的CompactDisc 还未被创建。接下来看一个完整的配置类:

@Configuration public class JavaConfig { /* * 声明一个简单的bean * */ @Bean public ClassicalMusic classicalMusic(){ return new ClassicalMusic(); } /* * 声明一个带有依赖对象的bean * 在这里通过使用构造器的方式来注入,当spring调用该方法时,它会自动装配一个CompactDisc导配置方法中 * */ @Bean public CDPlayer cdPlayer(CompactDisc compactDisc){ return new CDPlayer(compactDisc); } }

@Bean注解告诉Spring这个方法将会返回一个对象,该对象将会注册为Spring应用上下文中的bean。默认情况下bean的ID和方法名一致。 上述代码中生命了两个bean,即classicalMusic和cdPlayer,前者是一个简单的bean,而后者是一个带有依赖对象的bean,当spring调用该方法时,它会自动装配一个CompactDisc导配置方法中。 在这里需要以下三个需要注意的地方:

在声明带有依赖对象的bean时,必须首先声明被依赖的bean,即这里的classicalMusic(ClassicalMusic 实现了CompactDisc )。这里生成的bean是单例的,若你再声明一个实现了CompactDisc 接口的bean时,则会报错。带有@Bean注解的方法可以采用任何必要的Java功能来产生bean实例(构造器和Setter方法是@Bean方法的简单样例)。

既然上述代码已经配置好了,接下来接看一下如何使用已经配置好的bean,代码如下:

public class Test { public static void main(String[] args) { AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext(JavaConfig.class); CompactDisc compactDisc = (ClassicalMusic)configApplicationContext.getBean("classicalMusic"); compactDisc.play(); } } //结果 播放古典音乐

上述代码大致的执行原理如下:

通过创建AnnotationConfigApplicationContext 对象来配置后的Spring上下文,然后利用上下文来获取对应的bean,继而使用对应的方法。

三、XML装配

1、借助构造器注入初始化bean 两种基本的配置方式:

constructor-arg 元素使用Spring3.0中引入的c-命名空间

两者的区别在很大程度上就是是否繁琐以及c-命名空间不能注入集合。 下面来看一下一课程-老师的例子做个简单说明:

//课程类 public class Course { String courseName; double mark; public Course(String courseName, double mark) { this.courseName = courseName; this.mark = mark; } } //老师类 public class Teacher{ private Course course; public Teacher(Course course){ this.course = course; } public void teach() { System.out.println("我教的课程:"+course.courseName+" 绩点为:"+course.mark); } } //配置文件 //测试类 public class Test { public static void main(String[] args) { ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("com\\tyf\\day4\\ config.xml"); Teacher teacher = (Teacher) context.getBean("teacher"); teacher.teach(); } } //测试结果 我教的课程:数学 绩点为:4.0

上述代码仅仅说明了一个使用元素进行构造器注入初始化bean的一个很简单的方法,接下来再看一下如何使用c-命名空间来初始化bean(仅展示xml配置文件)。

可以看出使用c:-命名空间使得xml配置很简洁,易于读懂。_0说的是构造器中第一个参数,同理_1说的是构造器中第二个参数,一次类推。 那么如果构造器参数列表中有集合类型,则不能使用c:-命名空间,只能使用元素。假如课程中有一个选课学生名字并且使用构造器来注入该属性:

//课程类 public class Course { String courseName; double mark; List students;//选课学生姓名 public Course(String courseName, double mark,List studenets) { this.courseName = courseName; this.mark = mark; this.students = studenets; } } //教师类 public class Teacher{ private Course course; public Teacher(Course course){ this.course = course; } public void teach() { System.out.println("我教的课程:"+course.courseName+" 绩点为:"+course.mark); System.out.println("选课学生:"); for(String name:course.students){ System.out.println(name); } } } //测试类不变 //xml配置文件 Yafeng Xiaoshuang //结果 我教的课程:数学 绩点为:4.0 选课学生: Yafeng Xiaoshuang

从上述代码可以看出,list 是作为Constructor的一个子元素来进行工作的,list中又有value子元素用来给List中的属性赋值。

2、通过Setter方法注入属性

将Teacher类改为如下(其他不变):

//老师类 public class Teacher implements People { private Course course; public void setCourse(Course course){ this.course = course; } @Override public void teach() { System.out.println("我教的课程:"+course.courseName+" 绩点为:"+course.mark); System.out.println("选课学生:"); for(String name:course.students){ System.out.println(name); } } } //XML文件中改变的部分

这里注入属性的时候用的是property,其它基本和constructor基本一样。而构造器注入有c-命名空间,而Sertter属性注入方法也有一个p-命名空间,用法和c-命名空间一致。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有