Spring IOC Bean装配 --day07
碰到的问题,以及思考解决不在这里写,本人日记:记录觉得需要记得常用描述,具体实现相关知识点。写日记是为了梳理知识点加深记忆。可能缺少很多信息,如果您看到给您道个歉
一、概述
IOC 控制反转:传统开发中,通过new来实现手动创建对象,IOC思想则是通过第三方来获取对象,不管对象怎么来的,你需要就跟他(Spring)说就行了,实现原理也是基于反射。
IOC 容器:
Spring 提供 IoC 容器来管理和容纳我们所开发的各种各样的 Bean,并且我们可以从中获取各种发布在 Spring IoC 容器里的 Bean,并且通过描述可以得到它。
bean的理解,很好的一篇博文
Spring 容器设计
盗图:
1)BeanFactory: Spring IoC 容器所定义的最底层接口(getBean方法参数:Bean.class、“beanName”、“beanName”,Bean.class)。
2)ApplicationContext:Spring IoC 容器所定义最高级接口之一,使用最广泛的接口,功能强大,支持方法较多。
二、简单实现
导入相关包(过)Maven管理
pojo类
public class Clothes {
public Clothes()
{
System.out.println("一件衣服被创建了"+System.identityHashCode(this));
}
private String color;
private int size;
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public void destory(){
//System.identityHashCode(Object)方法可以返回对象的内存地址
System.out.println("这件衣服被销毁了"+System.identityHashCode(this));
}
}
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">
<bean class="my.test.Clothes" id="clothes" lazy-init="true" destroy-method="destory" >
<property name="color" value="red"/>
<property name="size" value="33"/>
</bean>
</beans>
测试类
//初始化容器
ApplicationContext applicationContext =new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
//getBean方法拿到对象
Clothes clothes1 = (Clothes)applicationContext.getBean("clothes");
//打印结果信息
System.out.println(clothes1.getColor()+clothes1.getSize());
结果
一件衣服被创建了1740846921
衣服颜色:red衣服尺码:33
三、Bean的装配
根据优先级排序 顺序3→2→1,但由于种种因素的限制有些装配无法实现,只能采用次一级优先级方法来实现装配。
1.xml文件中显示配置(二中配置)
简单易懂,当使用第三方类的时候,有些类并不是我们开发的,我们无法修改里面的代码只能使用xml进行配置。
<bean id="唯一标识,并不是必须 可以使用name代替 没有定义默认是全限定名#(0++)按定义次数递加" class="类的全限定名">
<!--设值注入简单类型-->
<property name="属性名" value="属性值" />
<!--属性也是一个Bean 通过refy引用-->
<property name="属性名" ref="另一个Bean的id或者name"/>
<property name="属性名" >
<ref bean="另一个Bean的id或者name"/>
</property>
<property name="属性名">
<value>另一种值写入方式</value>
<!--除了value 还可以 是Set、Map、List、Array、Properties 等-->
<!--和各自子节点的对应关系
list\Set\Array:value
Map:entry
Properties :property(必填key属性)
-->
</property>
</bean>
命名空间装配
c-命名空间:用于构造注入简化写法:
<!--未引入命名空间-->
<bean....>
<constructor-arg name="id" value="1" />
<constructor-arg name="name" value="学生1"/>
</bean>
<!-- 引入c- 命名空间后-->
<bean name="student2" class="pojo.Student"
c:id="2" c:name="学生2"/>
<!--如果需要设置引用的话在对应参数名后加上 (-ref) 比如:c:name-ref="beanId"
也可以用下标代替属性名
如:c:_0=""、c:_1=""
-->
p-命名空间:简化设置注入写法,写法和c-命名空间简写规则一样c换成p
util-命名空间:简化集合类元素
<!-- 引入util-命名空间之前 -->
<property name="list">
<list>
<ref bean="bean1"/>
<ref bean="bean2"/>
</list>
</property>
<!-- 引入util-命名空间之后 -->
<util:list id="list">
<ref bean="bean1"/>
<ref bean="bean2"/>
</util:list>
元素 | 描述 |
---|---|
<util:constant> | 引用某个类型的 public static 域,并将其暴露为 bean |
<util:list> | 创建一个 java.util.List 类型的 bean,其中包含值或引用 |
<util:map> | 创建一个 java.util.map 类型的 bean,其中包含值或引用 |
<util:properties> | 创建一个 java.util.Properties 类型的 bean |
<util:property-path> | 引用一个 bean 的属性(或内嵌属性),并将其暴露为 bean |
<util:set> | 创建一个 java.util.Set 类型的 bean,其中包含值或引用 |
通常一个配置文件写大量Bean配置信息会变得十分臃肿,可以通过import引入其他配置文件
写法:
<import resource="bean.xml" />
2.java类和接口中配置
可以减少xml文件中复杂的手动配置,可以实现自动装配。
两种使IOC容器能发现Bean的方法:
1)包扫描
定义扫描的包资源,让Spring IOC去扫描相应的包,将对应Bean装配进来
2)自动装配
通过注解定义,使得一些依赖关系可以通过注解完成。
@Component、@Value、@ComponentScan
简单规则:
@Component(value=“Bean的id,如果不写默认类名”)
@value(“下面属性的注入值”)
@ComponentScan:扫描当前包路径下的所有被@Compoent注解标记的pojo类。
示例代码:
//测试pojo类
package my.test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component(value="clothes")
public class Clothes {
public Clothes()
{
System.out.println("一件衣服被创建了"+System.identityHashCode(this));
}
@Value("red")
private String color;
@Value("31")
private int size;
//getter setter and others
}
//测试类
@ComponentScan
public class SpringTest {
public static void main(String args[])
{
//初始化容器
//ApplicationContext applicationContext =new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Clothes.class);
//getBean方法拿到对象
Clothes clothes1 = (Clothes)applicationContext.getBean("clothes",Clothes.class);
//打印结果信息
System.out.println("衣服颜色:"+clothes1.getColor()+"衣服尺码:"+clothes1.getSize());
}
}
实验成功
@Value(只能注入简单类型值,不能注入对象)、@ComponentScan(只能扫描当前包)
@ComponentScan配置项:
basePackages:Spring 根据它配置的信息去扫描对应的包以及子包,装配配置好的Bean
basePackageClasses:他会根据设定的类去自动查找到类所在的包,将配置好的Bean装配进来。
@ComponentScan(basePackages = "my.test")
@ComponentScan(basePackageClasses = my.test.Clothes.class)
注意:basePackages 和 basePackageClasses 选择
basePackages较简单且易读,因为设置过程中使用字符串传递参数,写入错误不会提示,在大量重构的项目中,经常需要修改报名 不适合使用。basePackageClasses 中包名变化,原来写入信息和当前包名不符合,或类名不符 IDE中会报错
@Autowired
通过它可以实现对象自动装配,用它标记一个自定义类型属性,等到Spring IOC 容器已经定位好所有Bean的时候,按照这个属性的自定义类型,去查找Bean,对这个属性实现装配
创建一个公司类型,让衣服类拥有一个公司属性,并用@Autowired
代码:
//公司
@Component(value="company")
public class Company {
@Value("小公司")
private String companyName;
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
}
//衣服加入对公司所在包的扫描、或扫描公司类
@Autowired
private Company company;
//getter、setter..
测试成功。
注意:
@Autowired默认能找到相应的Bean注入,如果注入失败会报错。解决方法:设置@Autowired(required = false) 设置注入失败不会报错。
注解不仅仅能配置在属性之上,还允许方法配置/
当发现多个相同类型的Bean 无法确定注入哪一个Bean:@Primary 标记一个类,这个类满足条件会被优先注入,@Qualifier指定注入的Bean的id
3.隐式Bean发现自动装配
@Bean
上面通过@Component来装配Bean,该注解使用在类上,引用第三方包的时候很不方便,&Bean可以用到到第三方包的方法上。
测试代码:
@Configuration//注解相当于 XML 文件的根元素,必须要,有了才能解析其中的 @Bean
public class BeanTest {
@Bean(name = "testName")
public String test()
{
System.out.println("测试Bean方法");
return "必须有返回值";
}
}
//测试类
// 在 pojo 包下扫描
ApplicationContext context = new AnnotationConfigApplicationContext("my.test");
context.getBean("testName");
((AnnotationConfigApplicationContext) context).close();
//测试成功
@Bean只用于方法,方法必须有返回值否则报错
Bean配置项
属性 | 作用 |
---|---|
name: | 是一个字符串数组,允许配置多个 BeanName |
autowire: | 标志是否是一个引用的 Bean 对象,默认值是 Autowire.NO |
initMethod: | 自定义初始化方法 |
destroyMethod: | 自定义销毁方法 |