spring框架bean注入

时间:2022-04-22 16:11:55

今天学习了spring框架,刚刚入门简单的了解了spring并学习了bean的注入IOC:IOC(Inversion of Control,控制反转)不是什么技术,而是一种设计思想。它的目的是指导我们设计出更加松耦合的程序。

引入:

  使用简单代码来实现推演  ,创建一个maven项目,开始我们的推演

创建一个bean类即常说的实体类如下:

spring框架bean注入

我们创建一个测试类 springTest,在测试类中操作,怎么样来获取Student类中 的信息呢(student类中有构造方法,无参,有参,有get,set方法,有studay() 方法 等等)

我们要怎么样来获取对象呢:

1.直接获取:

    @Test
public void springTest() {
Student student = new Student();
student.getStudy();
/*
* 输出 学生在学习
* */
}

上述代码是否显得太low了,因为假若有n个类使用这个对像,我们要在每一个类中new,假若你要修改,这样的一个工程量会有点大。

2.工具类获取:

spring框架bean注入

我们创建工具类来减少耦合性,在修改维护时只要修改工具类就行 代码调用:

  @Test
public void springTest02() {
Student stu = StudentBean.getStu();
stu.getStudy();
/*
* 输出 学生在学习
* */
}

这样就减少了一定的耦合性能,但在实际运用中,我们只可能只有一个实体类嘛当然不可能,如何提升性能并减少代码的耦合性呢

我们采用配置文件的方法建一个 beans.properties 存放bean的配置文件,并多创建一个实体类user

spring框架bean注入

重新再创建一个工具类BeanFactroy来编写我们的最终代码:

public class BeanFactory {
// 创建map集合存储对象
private static Map<String, Object> beanMap = new HashMap<String, Object>(); /*
* 在类初始化时读取beans配置文件中所有的bean类存储到map集合中
* */
static {
try {
ResourceBundle beans = ResourceBundle.getBundle("beans");// 读取beans配置文件
Enumeration<String> keys = beans.getKeys(); // 获取所有key值
while (keys.hasMoreElements()) {
String key = keys.nextElement(); // 获取每个key
String className = beans.getString(key); // 获取value
Class<?> aClass = Class.forName(className); // 通过反射得到该类
Object o = aClass.newInstance(); // 通过反射机制创建该类对象
beanMap.put(key, o); // 将k v值存入beanMap集合中
}
} catch (Exception e) {
e.printStackTrace();
}
} /* 创建静态方法供外界调用
* */
public static Object getBean(String beanName) {
return beanMap.get(beanName);
}
}

上面是工具类,下面是测试:

@Test
public void springTest03() {
User user = (User) BeanFactory.getBean("user");
user.getStudy();
/*
* 输出 我在学习
* */
}
@Test
public void springTest04() {
Student stu = (Student) BeanFactory.getBean("student");
stu.getStudy();
/*
* 输出 学生在学习
* */
}

上面的实例简单的展示来如何减少耦合性,最终下来,在管理对象时,我们只需要修改beans.properties 文件即可,更加方便管理下面进入spring的ioc容器使用

Bean容器注入:

第一步导包:

<properties>
<spring.version>5.2.9.RELEASE</spring.version>
<junit-version>5.6.2</junit-version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit-version}</version>
</dependency>
</dependencies>

第二步创建配置文件 applicationContext.xml  (认准下面的步骤)

spring框架bean注入

完成后如下:

spring框架bean注入

开始编写:

通过构造方法获取对象:

spring框架bean注入

测试代码:

    /*
* 读取app.xml文件 抽取出来
* */
private ApplicationContext ac = new ClassPathXmlApplicationContext("app.xml"); @Test
public void springTest05() {
User user1 = (User) ac.getBean("user1"); // user1与app.xml中bean里面的id值相对应
user1.getStudy();
// 打印 我在学习
}

读取xml方法:

  • ClassPathXmlApplicationContext: 从classpath目录读取配置文件
  • FileSystemXmlApplicationContext: 从文件系统或者url中读取配置文件
  • AnnotationConfigApplicationContext:当我们使用注解配置容器对象时,需要使用此类来创建 spring 容器,它用来读取注解。

使用前面的工厂来获取对象:

spring框架bean注入

测试代码:

    @Test
public void springTest06() {
User user1 = (User) ac.getBean("user2"); // user1与app.xml中bean里面的id值相对应
user1.getStudy();
// 打印 我在学习
}

在操作这里的时候我将BeanFactory修改了一点:

public class BeanFactory {
private String beanName;
private static Map<String, Object> beansObjectHashMap = new HashMap<String, Object>(); public BeanFactory() {
} public BeanFactory(String beanName) {
this.beanName = beanName;
} /*
* 采用静态代码块,在程序开始时,就将所有的对象存在beansObjectHashMap map集合中,使用时直接调用
* */
static {
try {
ResourceBundle beans = ResourceBundle.getBundle("beans");
Enumeration<String> keys = beans.getKeys();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
String className = beans.getString(key);
Class<?> aClass = Class.forName(className);
Object o = aClass.newInstance();
beansObjectHashMap.put(key, o);
}
} catch (Exception e) {
e.printStackTrace();
}
} // 采用配置文件获取对象 只能 获取一个
public static Object getBeanUser(String beanName) {
try {
ResourceBundle bundle = ResourceBundle.getBundle("beans");
String string = bundle.getString(beanName);
Class<?> aClass = Class.forName(string);
Object o = aClass.newInstance();
return o;
} catch (Exception e) {
e.printStackTrace();
return null;
}
} /*
* 当有多个实体类时 封装一个map集合返回
* */
public static Object getBeanMap(String beanName) {
return beansObjectHashMap.get(beanName);
}
/* public Object getBeanMap() {
return beansObjectHashMap.get(this.beanName);
}*/
}

Bean单例与多例:

    <!--
Bean单例与多例,在bean容器中添加有个scope属性,singleton代表单例
prototype 代表多例,单例获取的对象地址值是相同的,多例是不同的
调用案例就一样的不写了
-->
<bean id="user3" class="com.code.spring01.entity.User" scope="singleton"></bean> <!-- 单例 -->
<bean id="user4" class="com.code.spring01.entity.User" scope="prototype"></bean> <!-- 多例 -->
<!--
单例生命周期:容器创建时,就创建对象;容器摧毁时,就摧毁对象。
多例生命周期:getBean方法被调用时,创建对象,对象销毁与spring无关,等待垃圾回收机制回收
-->

set方法注入:

 <!--
使用set注入时,bean类中需存在get set 方法
set 方法注入 property和constructor-arg 使用时的区别
(不用在意顺序)property注入时可以单个属性的注入,即想写几个属性就写几个(不能超过)
constructor-arg 注入时,需全部属性都注入,否则会报错
-->
<bean id="stu2" class="com.code.spring01.entity.Student">
<property name="age" value="19"></property>
<property name="name" value="张三"></property>
</bean>
<!-- <bean id="stu2" class="com.code.spring01.entity.Student">
<constructor-arg name="name" value="张三"></constructor-arg>
</bean>-->
<!--
set 注入的简写 方式
-->
<bean id="stu3" class="com.code.spring01.entity.Student" p:name="王五" p:pwd="123" p:age="31" p:sex="男"/>

集合属性注入:

实体类:

public class Tec {
// 基本属性
private Integer id;
private String username;
private String password;
private Address address;
//list set array
private String[] str;
private List<String> list;
private Set<String> set; //map properties
private Map<String,String> map;
private Properties properties; // 省略了set方法

bean注入:

<bean id="user" class="com.hopu.ioc.User">
<property name="str">
<array>
<value>EE</value>
<value>FF</value>
</array>
</property>
<property name="list">
<list>
<value>AA</value>
<value>BB</value>
</list>
</property>
<property name="set">
<set>
<value>CC</value>
<value>DD</value>
</set>
</property> <property name="map">
<map>
<entry key="GG" value="gg"/>
<entry key="HH" value="hh"/>
</map>
</property>
<property name="properties">
<props>
<prop key="II">ii</prop>
<prop key="JJ">jj</prop>
</props>
</property>
</bean>

Bean的多模块注入:

当项目过于庞大时,为了开发便于维护和可读性,我们可以将bean配置文件模块化,采用导入模块方式优化管理

   <!--
在app.xml中导入app2.xml文件
-->
<import resource="app2.xml"/>

注解注入:

这个我没学,在百度上看了,简单模仿这操作一番:

@Component("admin")  // 等同于bean id="admin" class="com.code.spring01.entity.Admin"></bean>
@Scope(scopeName = "singleton") // 限制创建的为单例对象
//@Scope(scopeName = "prototype") // 限制创建的为多例对象
public class Admin {
private String name;
private String color; public Admin(String name, String color) {
this.name = name;
this.color = color;
} public Admin() {
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getAge() {
return color;
} public void setAge(String color) {
this.color = color;
} @Override
public String toString() {
return "Admin{" +
"name='" + name + '\'' +
", color='" + color + '\'' +
'}';
}
}

私有成员变量注入:

    @Value("BMW")
private String name;
@Value("Red")
private String color;

set方法注入:

 @Value("BMW")
public void setName(String name) {
this.name = name;
}
@Value("Red")
public void setColor(String color) {
this.color = color;
}

在使用时当然是bean容器更加方便管理一些,代码耦合性也低

个人学习,内容简略。