Spring IOC
GitHub: https://github.com/chauncycho/spring_test
IOC :Inverse-of-control 控制反转
反转的概念就是将原本在程序中手动创建实体对象的控制权,交给Spring框架管理
原理:配置+反射+工厂
通过配置,把实体class的位置写入配置文件,Spring框架便可以通过反射并通过工厂创建实体类
DI:Dependency-injection 依赖注入
依赖注入的概念,就是在Spring创建这个对象的过程中,将这个对象所依赖的属性给注入进去
简单流程
1.引入jar包
通过maven引入jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
2.创建实体类,这里我创建的是Food类,为属性添加setter
3.在src/main/resource中添加applicationContext.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
4.通过下面的代码便可通过Spring得到一个实体对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Food food = (Food) applicationContext.getBean("food");
Spring实例对象的三种方法
1.通过构造方法实例对象
如上简单流程
2.通过静态工厂实例对象
工厂类:
public class FoodStaticFactory {
public static Food getFood(){
System.out.println("通过静态工厂实例对象");
return new Food();
}
}
配置:
<!-- 通过静态工厂实例对象 -->
<bean id="food2" class="spring.ioc.FoodStaticFactory" factory-method="getFood"/>
实例:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Food food = (Food) applicationContext.getBean("food2");
3.通过实例工厂实例对象
工厂类:
public class FoodFactory {
public Food getFood(){
System.out.println("通过实例工厂实例对象");
return new Food();
}
}
配置:
<bean id="foodFactory" class="spring.ioc.FoodFactory"/>
<bean id="food3" factory-bean="foodFactory" factory-method="getFood"/>
实例:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Food food = (Food) applicationContext.getBean("food3");
Bean的配置
id和name
一般情况下,装配一个Bean时,通过指定一个id属性作为Bean的名称
id属性在IOC容器中必须是唯一的
如果Bean的名称中含有特殊字符,就需要使用name属性
class
class用于设置一个类的完全路径名称,主要作用是IOC容器生成类的实例
scope
通过scope设置Bean的作用范围:
scope | 作用 |
---|---|
singleton | 单例(每次得到的都是同一个对象) |
prototype | 普通(每次得到的都是一个新的对象) |
属性注入
<!--属性注入测试 -->
<bean id="person" class="spring.ioc.Person">
<property name="name" value="张三"/>
<property name="age" value="18"/>
<property name="food" ref="food4"/>
</bean>
<bean id="food4" class="spring.ioc.Food">
<property name="name" value="香蕉"/>
<property name="taste" value="甜甜的"/>
<property name="kind" value="水果"/>
</bean>
<!--p名称空间注入测试-->
<bean id="person2" class="spring.ioc.Person" p:age="18" p:name="张三" p:food-ref="food5"/>
<bean id="food5" class="spring.ioc.Food" p:name="苹果" p:kind="水果" p:taste="有点酸"/>
<!--SpEL属性注入测试-->
<bean id="person3" class="spring.ioc.Person">
<property name="name" value="#{'李四'}"/>
<property name="age" value="#{T(java.lang.Math).random() * 100}"/>
<property name="food" value="#{food6}"/>
</bean>
<bean id="food6" class="spring.ioc.Food">
<property name="name" value="#{'橘子'}"/>
<property name="kind" value="#{'水果'}"/>
<property name="taste" value="#{'特别酸'}"/>
</bean>
<!-- 复杂类型属性注入测试 -->
<bean id="collectionBean" class="spring.ioc.CollectionBean">
<property name="arr">
<list>
<value>111</value>
<value>222</value>
<value>333</value>
</list>
</property>
<property name="list">
<list>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>
<property name="set">
<set>
<value>123</value>
<value>456</value>
<value>789</value>
</set>
</property>
<property name="map">
<map>
<entry key="aaa" value="111"/>
<entry key="bbb" value="222"/>
<entry key="ccc" value="333"/>
</map>
</property>
</bean>
Bean的生命周期
1 | instantiate bean 对象实例化 |
2 | populate properties 封装属性 |
3 | 如果Bean实现BeanNameAware 执行 setBeanName |
4 | 如果Bean实现BeanFactoryAware 或者 ApplicationContextAware 设置工厂 |
5 | setBeanFactory 或者上下文对象 setApplicationContext5. setBeanFactory 或者上下文对象 setApplicationContext |
6 | 如果存在类实现BeanPostProcessor(处理Bean),执行postProcessBeforeInitialization |
7 | 如果Bean实现InitializingBean 执行afterPropertiesSet 调用 指定初始化方法 init |
8 | 如果类存在类实现 BeanPostProcessor(处理Bean),执行postProcessAfterInitialization |
9 | 执行业务处理 |
10 | 如果Bean实现 DisposableBean 执行destroy |
11 | 调用指定销毁方法customerDestroy |
通过注解管理Bean
简单使用
- maven额外引入spring-aop
- xml配置文件修改
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启注解扫描 -->
<context:component-scan base-package="spring.ioc"/>
</beans>
- 在类中添加注解
@Component("[id]")
就相当于配置了一个id为注解中的id,class为当前类的bean
更多注解
- 除了@Component外,Spring提供了3个功能基本和@Component等效的注解,如下:
@Repository 用于对DAO实现类进行标注
@Service 用于对Service实现类进行标注
@Controller 用于对Controller实现类进行标注
- 属性为对象的注入
通过在属性前添加@Autowired,Spring会自动注入
若想通过id进行注入,则还需加上@Qualifier("[id]")
也可以通过@Resource(name="[id]")代替前两句
- Bean的创建与销毁
Spring初始化bean或销毁bean时,有时需要做一些处理工作,因此spring可以在创建和拆卸bean的时候调用bean的两个生命周期方法(必须是scope = singleton 单例模式 ),同时,只有声明为ClassPathXMLApplicationContext才能使用close方法(或者是ApplicationContext的其他子类)
当bean被载入到容器的时候调用init,注解方式如下:
@PostConstruct
当bean从容器中删除的时候调用destroy方法,注解方式如下:
@PreDestroy
- 使用注解配置Bean的作用范围
通过@Scope注解,指定Bean的作用范围,scope属性具体可往上看Bean的配置
关于Spring更方便的测试
可以配置maven
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
使用可参照下面
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo {
//注入
@Resource(name = "studentDao")
private StudentDao studentDao;
@Test
public void demo1(){
studentDao.find();
studentDao.save();
studentDao.update();
studentDao.delete();
}
}