一、需要导入的Jar文件。
jar文件的作用:
二、代码演示:
我们知道,spring对象属性的注入方式有两种:设值注入和构造注入。先看代码:
假如,我们有下面一个类People,人有不同的属性:年龄、名字、性别,那么下面的通过设值注入和构造注入两种方式进行演示。
1、设值注入代码:
public class PeopleImpl { /* * 年龄 */ public int Age; /* * 名字 */ public String Name; /* * 性别 */ public String Sex; public void setAge(int age) { Age = age; } public void setName(String name) { Name = name; } public void setSex(String sex) { Sex = sex; } public void Show() { System.out.println("PeopleImpl [Age=" + Age + ", Name=" + Name + ", Sex=" + Sex + "]"); } }
配置文件(名称任意,此处为Bean.xml):
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 注意:Class必须为类的限定名;name的值必须和Set的值保持一致 --> <bean id="GetPeople" class="DI_Setting.PeopleImpl"> <property name="Age" value="25"></property> <property name="Name" value="王五"></property> <property name="Sex" value="男"></property> </bean> </beans>
2、构造函数注入:
public class PeopleImpl { // 年龄 public int Age; // 名字 public String Name; // 性别 public String Sex; // 构造函数赋值 public PeopleImpl(int age, String name, String sex) { super(); Age = age; Name = name; Sex = sex; } public void Show() { System.out.println("PeopleImpl [Age=" + Age + ", Name=" + Name + ", Sex=" + Sex + "]"); } }
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 注意:Class必须为类的限定名;name的值必须和构造函数的值保持一致 --> <bean id="GetPeople" class="DI_ConStructor.PeopleImpl"> <constructor-arg name="age" value="26"></constructor-arg> <constructor-arg name="name" value="王五"></constructor-arg> <constructor-arg name="sex" value="男"></constructor-arg> </bean> </beans>
运行测试代码:
//测试类型 public class Test { @org.junit.Test public void Show() { //路径-配置文件所在的路径 String Path="DI_Setting/Bean.xml"; //获取Application对象 ApplicationContext context=new ClassPathXmlApplicationContext(Path); //获取的Bean的名字一定要和配置文件实例的对象名称保持一致 PeopleImpl people=(PeopleImpl) context.getBean("GetPeople"); people.Show(); } }
3、三层架构下实例获取:
在实际的开发过程中,我们大多数采用采用三层架构:UI层负责显示和提交数据,Server层负责业务逻辑。Dao层负责数据交互。下面的代码用构造注入的方式演示三层架构下的调用。
Server层:
public interface IUserServer { //添加用户 public void AddUser(); }
public class UserServerImpl implements IUserServer { private IUserDao IUserDao; public UserServerImpl(IUserDao Dao) { this.IUserDao=Dao; } //添加用户 @Override public void AddUser() { // TODO 自动生成的方法存根 this.IUserDao.AddUser(); } }
Dao 层:
public interface IUserDao { //添加用户 public void AddUser(); }
public class UserDaoImpl implements IUserDao { //此处模拟添加用户 @Override public void AddUser() { System.out.println("用户添加成功!"); } }
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 重点: <constructor-arg>应用于构造注入,<property>应用于设值注入 ref指向的是另一个Bean的Id的应用,并且这个id要和构造函数中参数值名称保持一致 --> <bean id="GetInstance" class="DI_ConStructor_SanCeng.UserServerImpl"> <constructor-arg name="Dao" ref="IDao"></constructor-arg> </bean> <!-- 上面的<constructor>指向了这个Bean --> <bean id="IDao" class="DI_ConStructor_SanCeng.UserDaoImpl"></bean> </beans>
测试:
//测试类型 public class Test { @org.junit.Test public void Show() { //路径-配置文件�?在的路径 String Path="DI_ConStructor_SanCeng/Bean.xml"; //获取Application对象 ApplicationContext context=new ClassPathXmlApplicationContext(Path); //获取的Bean的名字一定要和配置文件实例的对象名称保持一致 IUserServer IUser=(IUserServer) context.getBean("GetInstance"); IUser.AddUser(); } }
三、总结:
这两种依赖注入的方式,并没有绝对的好坏,只是适应的场景有所不同,
设值注入有如下优点:
- 设值注入需要该Bean包含这些属性的setter方法
- 与传统的JavaBean的写法更相似,程序开发人员更容易理解、接收。通过setter方法设定依赖关系显得更加只管
- 对于复杂的依赖关系,如果采用构造注入,会导致构造器国语臃肿,难以阅读。Spring在创建Bean实例时,需要同时实例化器依赖的全部实例,因而导致性能下降。而使用设值注入,则能避免这些问题
- 尤其是在某些属性可选的情况况下,多参数的构造器显得更加笨重
构造注入有如下优点:
- 构造注入需要该Bean包含带有这些属性的构造器
- 构造注入可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入。例如,组件中其他依赖关系的注入,常常要依赖于DataSrouce的注入。采用构造注入,可以在代码中清晰的决定注入顺序。
- 对于依赖关系无需变化的Bean,构造注入更有用处。因为没有Setter方法,所有的依赖关系全部在构造器内设定。因此,无需担心后续的代码对依赖关系产生破坏。
- 依赖关系只能在构造器中设定,则只有组件的创建者才能改变组件的依赖关系。对组件的调用者而言,组件内部的依赖关系完全透明,更符合高内聚的原则。
采用以设值注入为主,构造注入为辅的注入策略。对于依赖关系无需变化的注入,尽量采用构造注入;而其他的依赖关系的注入,则考虑采用设值注入。