基础定义
IOC是一种思想,其实现方式多种多样,当前比较流行的方式有两种,依赖注入和依赖查找
- 依赖查找:容器提供回调接口和上下文环境给组件,程序代码需提供具体的查找方式
- 依赖注入:程序代码不做代码调查,这些工作由容器自行完成
- 依赖注入DI是指程序运行过程中,若需要调用另一个对象的协助,无需再代码中创建被调用者,而是依赖于外部容器,由外部容器创建后传递给程序
IOC实现
- 完整程序实现过程
- 导入包文件
此时需要了解spring的框架如下,依据图例可知最少需要以下核心包:
spring-beans、spring-context、spring-core、spring-express;
为了辅助测试辅助包如:
com.springsource.junit
com.springsource.org.apache.commons.logging
com.springsource.org.apache.log4j
- 创建类与接口
- 配置配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"wan
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">
<!--注册service -->
<bean id="myService" class="com.jd.wang.SomeServiceImpl">
</bean>
</beans>
- 书写样例
- 接口与实现
package com.jd.wang;
public interface ISomeService {
void doSome();
}
package com.jd.wang;
import org.junit.Test;
public class SomeServiceImpl implements ISomeService {
public void doSome() {
// TODO Auto-generated method stub
System.out.println("执行 doSome");
}}
- 测试类
package com.jd.wang.test;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import com.jd.wang.ISomeService;
public class MyTest {
@Test
public void test01(){
//加载容器对象,加载spring配置文件
ApplicationContext ac = new
ClassPathXmlApplicationContext("applicationContext.xml");
ISomeService service = (ISomeService) ac.getBean("myService");
service.doSome();}
//ApplicationContext 与BeanFactory容器的区别:
//1)ApplicationContext容器再进行初始化时会将其中的所有Bean对象进行创建
//2)BeanFactory容器中的对象,在容器初始化时并不会被创建,而是在真正获取对象时被创建
@Test
public void test02(){
BeanFactory bf = new XmlBeanFactory(new
ClassPathResource("applicationContext.xml"));
ISomeService service = (ISomeService)
bf.getBean("myService");service.doSome();}
- 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"wan
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">
<!--注册service -->
<bean id="myService" class="com.jd.wang.SomeServiceImpl">
</bean>
</beans>
- 动态工厂
- 工厂类
package com.jd.wang;
public class ServiceFactory {
public SomeServiceImpl getSomeService()
{
return new SomeServiceImpl();
}
- 配置配置文件
<?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 id="factory" class="com.jd.wang.ServiceFactory"></bean>
<bean id="myService" factory-bean="factory" factory
method="getSomeService"></bean>
</beans>
- 静态工厂
- 工厂类
package com.jd.wang;
public class ServiceFactory
{
public static SomeServiceImpl getSomeService()
{
return new SomeServiceImpl();
}
}
<?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 id="myService" class="com.jd.wang.ServiceFactory" factory-method="getSomeService"></bean>
</beans>
- bean作用域
- 原型模式
原理:
对象的创建时机不是在spring容器初始化时创建,而是在代码真正访问时才创建
配置关注点:
<bean id="myService" class="com.jd.wang.SomeServiceImpl" scope="prototype"></bean>
测试用例:
ApplicationContext ac = new ClassPathXmlApplicationContext("com/jd/wang/applicationContext.xml");
ISomeService service = (ISomeService) ac.getBean("myService");
ISomeService service2 = (ISomeService) ac.getBean("myService");
System.out.println(service == service2);//返回值为false
- 单例模式
原理:
对象的创建时机是在spring容器初始化时创建
配置关注点:
<bean id="myService" class="com.jd.wang.SomeServiceImpl" scope="singleton"></bean>
测试用例:
ApplicationContext ac = new ClassPathXmlApplicationContext("com/jd/wang/applicationContext.xml");
ISomeService service = (ISomeService) ac.getBean("myService");
ISomeService service2 = (ISomeService) ac.getBean("myService");
System.out.println(service == service2);//返回为true
- bean后处理器
- 实现自己的bean后处理器
package com.jd.wang;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {//必须实现BeanPostProcessor
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
// TODO Auto-generated method stub
//此处的bean表示当前正在初始化的bean对象
//此处的beanName表示当前正在初始化的bean对象的id
System.out.println("before");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
// TODO Auto-generated method stub
//此处的bean与上文的bean有相同的意义
System.out.println("after");
return bean;
}
}
- 配置文件
//只需要新增一行:
<bean class="com.jd.wang.MyBeanPostProcessor"></bean>
- 测试实例
ApplicationContext ac = new ClassPathXmlApplicationContext("com/jd/wang/applicationContext.xml");
ISomeService service = (ISomeService) ac.getBean("myService");
service.doSome();
- 定制bean的生命始末
- 定义实体类
package com.jd.wang;
import org.junit.Test;
public class SomeServiceImpl implements ISomeService {
public SomeServiceImpl()
{
System.out.println("创建对象");
}
public void doSome() {
// TODO Auto-generated method stub
System.out.println("执行 doSome");
}
public void setUp(){
System.out.println("生命起始");
}
public void tearDown(){
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">
<bean id="myService" class="com.jd.wang.SomeServiceImpl" init-method="setUp" destroy-method="tearDown"></bean>
<bean class="com.jd.wang.MyBeanPostProcessor"></bean>
</beans>
- 配置
ApplicationContext ac = new ClassPathXmlApplicationContext("com/jd/wang/applicationContext.xml");
ISomeService service = (ISomeService) ac.getBean("myService");
service.doSome();
- Bean的生命周期
- 构造函数
- 参数的诸如
- 如果实现了BeanNameAware,则可以获取bean的id
- 如果实现了BeanFactoryAware,则可以获取BeanFactory容器
- bean后处理器的Before方法
- 如果实现了InitializingBean则会执行AfterPropertiesSet,标志着初始化执行结束
- 执行bean定义的init-method方法
- bean后处理器的After方法
- 执行业务方法,自定义的方法等
- 如果继承了DisposableBean,执行destory方法(销毁之前)
- 执行bean定义的destory-method方法
- 赋值问题
配置文件
<?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 id="mySchool" class="com.jd.wang.School">
<property name="name" value="清华大学 "></property>
</bean>
<bean id="mySchool2" class="com.jd.wang.School">
<property name="name" value="北京大学 "></property>
</bean>
<bean id="mySome" class="com.jd.wang.Some">
<property name="schools">
<array>
<ref bean="mySchool"/>
<ref bean="mySchool2"/>
</array>
</property>
<property name="myStrs">
<array>
<value>中国</value>
<value>北京</value>
</array>
</property>
<property name="myList">
<list>
<value>大兴</value>
<value>义庄</value>
</list>
</property>
<property name="mySet">
<set>
<value>大族企业湾</value>
<value>10号楼</value>
</set>
</property>
<property name="myMap">
<map>
<entry key="mobile" value="17809290119"></entry>
<entry key="qq" value="1234567"></entry>
</map>
</property>
<property name="myPros">
<props>
<prop key="education">大学</prop>
<prop key="gender">男</prop>
</props>
</property>
- 自动注入之名称注入
<?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 id="school" class="com.jd.wang.School">
<property name="name" value="school"></property>
</bean>
<!--
autowire="byName" 会从容器中查找与实体类的域属性名同名的bean的id,并将该bean对象自动注入给该域属性
-->
<bean id="myStudent" class="com.jd.wang.Student" autowire="byName">
<property name="name" value="张三"></property>
<property name="age" value="23"></property>
</bean>
</beans>
- 自动注入之类型注入
<?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 id="mySchool" class="com.jd.wang.School">
<property name="name" value="school"></property>
</bean>
<!--
autowire="byType" 会从容器中查找与实体类的域属性类型相同的bean,并将其注入给域属性(有多个时会报错)
-->
<bean id="myStudent" class="com.jd.wang.Student" autowire="byType">
<property name="name" value="张三"></property>
<property name="age" value="23"></property>
</bean>
</beans>
- 使用SPEL表达式注入
<?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 id="myPerson" class="com.jd.wang.Person">
<property name="pname" value="李四"></property>
<property name="page" value="#{T(java.lang.Math).random()*50}"></property>
</bean>
<!--
autowire="byType" 会从容器中查找与实体类的域属性类型相同的bean,并将其注入给域属性(有多个时会报错)
-->
<bean id="myStudent" class="com.jd.wang.Student" autowire="byType">
<property name="name" value="#{myPerson.pname}"></property>
<property name="age" value="#{myPerson.page}"></property>
</bean>
</beans>
- 使用内部Bean注入
<?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 id="myStudent" class="com.jd.wang.Student">
<property name="name" value="wang"></property>
<property name="age" value="23"></property>
<property name="school">
<bean class="com.jd.wang.School">
<property name="name" value="清华大学"></property>
</bean>
</property>
</bean>
</beans>
- 抽象bean
-
同类抽象bean
<?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 id="baseStudent" class="com.jd.wang.Student" abstract="true"> //此bean为抽象bean <property name="school" value="清华大学"></property> <property name="department" value="计算机系"></property> </bean> <bean id="myStudent" parent="baseStudent"> <property name="name" value="王斌斌"></property> <property name="age" value="23"></property> </bean> </beans>
-
异类抽象bean
<?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 id="base" abstract="true"> <property name="school" value="清华大学"></property> <property name="department" value="计算机系"></property> </bean> <bean id="myStudent" class="com.jd.wang.Student" parent="base"> <property name="name" value="王斌斌"></property> <property name="age" value="23"></property> </bean> <bean id="myTeacher" class="com.jd.wang.Teacher" parent="base"> <property name="name" value="Reyco"></property> <property name="workAge" value="18"></property> </bean> </beans>
- 为应用指定多个配置文件
- 配置文件中指定
<?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">
<import resource="classpath:com/jd/wang/base.xml"/>
<import resource="classpath:com/jd/wang/bean.xml"/>
</beans>
- 应用程序中指定
ApplicationContext ac = new ClassPathXmlApplicationContext("com/jd/wang/spring-base.xml","com/jd/wang/spring-bean.xml");
- 通配符指定
ApplicationContext ac = new ClassPathXmlApplicationContext("com/jd/wang/pring-*.xml");
- 注解
- School类定义
package com.jd.wang;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("mySchool") //表示当前类被spring容器管理
public class School {
@Value("清华大学")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- Student类
package com.jd.wang;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("myStudent")
public class Student {
@Value("张三")
private String name;
@Value("23")
private int age;
@Autowired //byType方式的注解式注入
@Qualifier("mySchool") //byName方式的注解式注入,要求@Autowired与 @Qualifier联合使用
//@Resource(name="mySchool")表示byName @Resource表示byType
private School school;
private String department;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", school=" + school
+ ", department=" + department + "]";
}
}
- 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here -->
<context:component-scan base-package="com.jd.wang"></context:component-scan>//可以使用通配符
</beans>
- 三种相同的注解
- @Repository注解在Dao实现类上
- @Service注解在Service实现类上
- @Controller注解在SpringMVC的处理器上
这些注解功能完全相同,只是意义不同
- bean的生命始末注解
@PostConstruct
public void initAfter()
{
System.out.println("创建后");
}
@PreDestroy
public void preDestory()
{
System.out.print("销毁前");
}
- 使用JavaConfig进行配置
- 定义容器类
package com.jd.wang;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyJavaConfig {
@Bean(name="mySchool")
public School mySchoolCreator()
{
return new School("北京大学");
}
@Bean(name="myStudent")
public Student myStudentCreator()
{
return new Student("张三",23);
}
}
- 定义配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here -->
<context:component-scan base-package="com.jd.wang"></context:component-scan>
</beans>
- 优先级问题
XMl的优先级要高于注解