Spring IoC 的基本使用
〇、关于spring
- spring是一个容器,装对象和对象关系的容器
- spring核心技术有IOC(控制反转)和AOP(面向切面编程)
IOC
一、IoC容器的初始化过程
1.资源定位(配置文件);
2.Bean信息的载入(将配置好的信息转化成spring内部表示的数据结构);
3.对bean配置属性解析;
4.解析好的bean在IoC容器注册(提供更友好的使用方式);
二、依赖注入
实例化用户索要的bean;
把bean之间的依赖关系设置好;
三、bean生命周期
当使用ApplicationContext时:ApplicationContext启动->实例化bean->为属性赋值->前置处理器->bean指定初始化方法->后置处理器->使用bean->bean的销毁方法;
当使用BeanFactory时:在getBean()之后进行上述过程;
四、bean配置
- 属性配置
<bean id=”” class=””>
<property name=”属性名” value=”值”></property>
<property name=”属性名” ref=”引用另外bean的id”></property>
</bean>
属性配置,要在javabean里面有该属性的set方法;
得有个无参构造方法;
Property标签 可以使用type属性指定其数据类型;
- 构造器配置
<bean id=”” class=””>
<constructor-arg value=”参数值”></constructor-arg>
<constructor-arg ref=”引用另外bean的id”></constructor-arg>
</bean>
可以使用type属性设置其数据类型
- 级联属性赋值
<bean id=”” class=””>
<constructor-arg ref=”引用另外bean的id”></constructor-arg>
<property name=”(另外bean的id).(其属性)” value=”值”></property>
</bean>
使用级联时,注意要先将级联的bean初始化
- 内部bean
<property name=”一个要引用的bean”>
<bean class=””>
……
</bean>
</property>
将内部的bean赋值给property;
内部bean只能在内部使用;
- 特殊字符
若有一些xml文档会默认解析的字符(如<>),可以使用<![CDATA[]]>
<property name=””>
<value><![CDATA[<hello>]]></value>
</property>
- Null值
使用<null/>
- 配置有List属性的bean
<property name=”类型为List的属性名”>
<list>
<ref bean=”bean的id”/>
//基本数据类型使用value
//也可以使用一个内部bean
</list>
</property>
- 配置有Map属性的bean
<property name=”类型为map的属性名”>
<map>
<entry key=”key值” value-ref=”引用的类型的键值”></entry>
</map>
</property>
- 将集合数据提取出来,以供多个bean重用(以list为例)
//要先引入util命名空间
<util:list id=”该集合数据的id”>
<ref bean=”一个bean的id”>
//基本数据类型使用value
</util:list>
在bean配置中,属性就写成如下:
<property name=”类型为List的属性名” ref=”集合数据的id”></property>
- 通过p命名空间,简写为bean属性赋值
//先引入p命名空间
<bean id=”bean的id” class=”该bean的类路径” p:第一个属性名=”值”
P:第二个属性名=”值” p:第三个属性名-ref=”引用bean的id” …..>
</bean>
- 自动装配
在bean中加入autowire="byType" 或者autowire="byName",可以自动匹配类型相同的参数或者名字相同的参数,不过要是无响应参数则返回null,有多个相应参数则报错;
- 作用域
每一个bean默认是单例(singleton)的,在容器初始化时自动地创建了bean实例,然后在每次向容器要bean时都是同一个实例;
在bean中加入scope属性,值设为”prototype”,即(scope=”prototype”),就只会在向容器索取bean时才创建bean实例,并且是每次不同的实例;
- 使用外部配置文件
先引用context命名空间,然后使用
<context:property-placeholder location="classpath:配置文件路径"/>
把外部的配置文件引用进来,再使用${“键“}使用外部配置文件中的数据;
- 使用SpEL为bean赋值
可以在值中,写入#{数字},#{”字符串”},#{true/false},#{T(静态类).方法},
#{+-*/},其它bean或其他bean的方法#{beanID}、#{beanID.属性},#{beanID.方法()},#{逻辑判断(><==?:)},正则表达式;
- Bean生命周期中的指定初始化方法、指定销毁方法,所有bean的前置/后置处理器
1.在bean配置中使用init-method=“bean的某个方法”,在bean实例化完成、属性赋值完成之后,会调用这个’ bean的某个方法’;destroy-method同理;
2.新建一个类,实现‘BeanPostProcessor’接口,该接口中有两个方法,其中postProcessBeforeInitialization(参数1,参数2)为前置处理器,在运行指定的初始化方法之前会先运行该方法,参数1为bean本身,参数2为bean的ID;同理,postProcessAfterInitialization(参数1,参数2)在运行指定的初始化方法之后执行;
每个bean初始化都会调用同一个前置/后置处理器,要使用前/后置处理器,得在配置文件中写入<bean class=”实现处理器接口的类的路径”></bean>
- 工厂方法配置bean
1.调用静态工厂方法创建Bean是将对象创建的过程封装到静态方法中,当客户端需要对象时,只需要简单地调用静态方法,而不用关心创建对象的细节;
2.新建一个工厂类,将需要使用的bean在工厂的无参构造函数或静态代码块中实例化,并把实例存在工厂类的一个map里(键位bean名,值为bean本身),而后在工厂类使用getBeanName(参数)的方法来获取bean(称这个方法为工厂方法);
3.(1)通过静态工厂方法获取bean:工厂方法要使用static字段,然后在配置文件中配置工厂类的bean,
<bean id=”beanID” class=”工厂类路径” factory-method=”getBeanName”>
使用<constructor-arg value="beanName" />属性来获取指定的bean
使用<property name="要使用的bean里的字段" value="值" />属性来为bean属性赋值
(2)通过实例工厂方法获取bean:工厂方法不需要使用static关键字;
先独自配置工厂类的bean:<bean id=”工厂类ID” class=”工厂类路径” />
然后逐一配置需要使用的bean,在bean中使用factory-bean=" " 和factory-method=" "指定工厂beanID和工厂方法,< constructor-arg >属性和<property>属性使用同上;
- 通过FactoryBean配置bean
- 创建一个bean,并实现FactoryBean<T>接口;
- 可以在bean内写字段或其它方法;
- 配置好bean后,在程序中每次获取这个bean其实都是调用了FactoryBean<T>接口的getObject()方法;
- 所以你想要返回什么样的bean就在getObject()方法中做操作
- 注解配置
- 要使用注解前,在xml配置文件中写入组件扫描器:
(1)<context:component-scan base-package="包名" resource-pattern=”指定扫描的类(该属性可不写)”>
</context:component-scan>
(2)IOC容器会扫描该包和该包子包的注解了的类、字段、方法;
(3)其中,该标签有<context:include-filter type=” annotation/assignable” expression =”注解类路径/bean类路径”>用此标签指定需要的目标类(annotation表示以指定注解方式,assignable表示以指定类方式),该标签与context:component-scan内部属性use-default-filters="true/false"一起使用,当use-default-filters为false时,IOC只会扫描context:include-filter指定的注解或者类;其它的注解或者类不在扫描,当它们没配置;
(4) <context:exclude-filter type=” annotation/assignable” expression =”注解类路径/bean类路径”>同理,表示不包含某注解或某类,不需要和use-default-filters="true/false"一起使用;
1.在需要配置成bean的类上写上(@Component、@Repository、@Service、@Controller)四个注解是等效的,其中@Component泛指bean组件,当bean不好归类时,用这个;之所以有四个等效的bean组件注解,因为在三层架构中很容易看出后 3 个注解分别和持久层、业务层和控制层(Web 层)相对应;
2.属性或者方法的参数使用@Autowired来注入依赖,@Autowired会自动找到类型相同的bean(当有多个类型相同的bean时,会根据变量名来找相应的bean名,当变量名都一样时,使用@Qualifier("bean唯一ID"));
3.@Resource与@Autowired功能类似,只不过@Resource要指定一个bean名;
4.@Value(“”)用在基本类型属性上,赋值;
5.@Scope(“”)指定bean的作用域,同XML;
6.@PostConstruct指定初始化方法,@PreDestroy指定销毁方法;
- 泛型的注解注入
使用@Autowired
- 用一个java类来充当配置文件
(1)首先新建一个类,在类上使用@Configuration表明该类为配置类
(2)在类中定义方法,方法返回的是bean的实例对象(return new XXBean),在该方法上加上@Bean(name=”beanID”),表示该方法为一个bean(等同xml配置文件中的一个<bean></bean>),该属性的属性赋值使用bean的带参构造器即可(new XXBean(参数1,参数2….));
(3)当bean内有需要注入的其它对象时,在@Bean中使用autowire,@Bean(name=”beanID” autowire=Autowire.byType/byName),byType表示自动注入相应类型的其它bean到当前bean需要注入的地方,byName表示自动注入同名的bean到当前bean需要注入的地方;
(4)与此同时,在bean类中就无需加入任何注解了,而获取该bean的方法同之前一样(ApplicationContext …….);
- 注解与XML配置文件
(1) 当两者都对bean配置时,XML配置文件优先;
(2) 注解可以直接写在属性上,不需要get,set方法;
(3) XML配置文件为属性赋值时,必须得有get,set方法;
ps.请另外查阅开发过程中需要使用的jar包