spring的IOC,控制反转
Ioc全称Inversion of Control,即“控制反转”,这是一种设计思想。对象创建的权利由Spring框架完成.由容器管理对象的生命周期.
入门案例:(xml配置文件的方式)
1.定义行为规范的接口Pet
package com.jt.demo1;
public interface Pet {
void hello();
}
2.定义接口的实现类:Dog类
package com.jt.demo1;
public class Dog implements Pet {
public Dog(){
System.out.println("我是无参构造~~~");
}
@Override
public void hello() {
System.out.println("小狗汪汪汪~~~");
}
}
3.在resources目录下配置xml文件spring.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">
<!--
1. IOC的机制管理Dog对象
id: 对象的唯一标识符. 不能重复 见名知意 首字母小写
class: 类路径
-->
<bean id="dog" class="com.jt.demo1.Dog"></bean>
</beans>
4.创建测试类User,查看程序运行效果
public class User {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("spring.xml");
Dog dog = (Dog) app.getBean("dog");
dog.hello();
}
}
IOC机制的原理
容器的数据结构: K-V Map<K,V> key=bean中的ID, value=实例化的对象
程序执行过程:
- 指定配置文件的名称.
- 当Spring容器加载配置文件时.当按照顺序执行bean标签时,开始创建对象.
- Spring通过bean标签中的class属性获取类型的路径,之后通过反射机制,实例化对象(必须有无参构造)
- bean中的Id当做Map中的key, 将实例化的对象保存到Map中,当做value. 至此Spring容器启动成功!!!
- 当用户需要获取对象时,可以通过key/或者类型 获取对象.
spring注解开发(改造入门案例)
1.定义行为规范的接口Pet
package com.jt.demo1;
public interface Pet {
void hello();
}
2.定义接口的实现类:Dog类
package com.jt.demo1;
public class Dog implements Pet {
public Dog(){
System.out.println("我是无参构造~~~");
}
@Override
public void hello() {
System.out.println("小狗汪汪汪~~~");
}
}
3.定义配置类SpringConfig
package com.jt.demo4;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
@ComponentScan("com.jt.demo4") //包扫描注解,让Spring注解生效!!!
@Configuration //标识当前类是配置类
public class SpringConfig {
//作用:和配置文件类似,管理对象
/*
IOC-写法
1.@Bean 告诉Spring容器,当前方法的名称,为Map中的key
返回值是Map中的value
2.特殊用法:常规条件下,Spring通过反射实例化对象,也可以由用户自己创建
*/
@Bean
public Dog dog(){
return new Dog();
}
}
4.创建测试类User,查看程序运行效果
package com.jt.demo4;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class User {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
Dog dog = context.getBean(Dog.class);
dog.hello();
}
}
Spring管理对象 方式一:(@Bean)
Bean容器对象的生命周期方法
package com.jt.demo6;
/*
Day03
spring对象的生命周期
*/
/**定义User类*/
public class User {
//1.对象创建,Bean创建对象自动调用
public User(){
System.out.println("用户对象创建成功");
}
//2.进行初始化
@PostConstruct //初始化注解
public void init(){
System.out.println("为属性赋值");
}
//3.进行业务调用,业务方法,用户手动调用
public void hello(){
System.out.println("我爱java");
}
//4.销毁方法
@PreDestroy //标记为销毁方法
public void destroy(){
System.out.println("调用销毁方法,释放资源");
}
}
/**创建配置类*/
@Configuration //标识配置类
public class SpringConfig {
@Bean //把对象控制权交给Bean
public User user(){
return new User();
}
}
/**测试类*/
public class TestUser {
public static void main(String[] args) {
//ApplicationContext app1 = new AnnotationConfigApplicationContext(SpringConfig.class);
AnnotationConfigApplicationContext app2 = new AnnotationConfigApplicationContext(SpringConfig.class);
User user = app2.getBean(User.class);
//调用业务方法
user.hello();
//如果需要执行销毁方法,则需要先关闭容器对象
//知识点:容器的接口,没有提供关闭容器的操作,需要调用实现类的关闭方法
//设计思想:销毁动作是敏感行为,特殊处理,实现类中有关闭方法
//app1.close();//报错,接口中没有关闭方法
app2.close();//先调用销毁方法,然后关闭容器
}
}
Spring管理对象 方式二:(@Component)
容器对象的生命周期方法
package com.jt.demo6;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/*spring自动为该注解标识的类,通过反射实例化对象,
交给spring容器管理,
key:类名首字母小写user
value:反射机制创建出来的对象
类似于@Bean注解
@Component/@Bean区别:
1.@component spring容器通过反射自动创建对象
@Bean 是用户自己手动创建的对象
2.@component 是标识类的
@Bean 标识配置类中的方法
3.@component 对象的Id是类名的首字母小写
@Bean 对象的Id是方法名
*/
@Component
public class User {
//1.对象创建,Bean创建对象自动调用
public User(){
System.out.println("用户对象创建成功");
}
//2.进行初始化
@PostConstruct //初始化注解
public void init(){
System.out.println("为属性赋值");
}
//3.进行业务调用,业务方法,用户手动调用
public void hello(){
System.out.println("我爱java");
}
//4.销毁方法
@PreDestroy //标记为销毁方法
public void destroy(){
System.out.println("调用销毁方法,释放资源");
}
}
/**配置类*/
@Configuration //标识配置类
@ComponentScan("com.jt.demo6")
public class SpringConfig {
}
/**测试类*/
public class TestUser {
public static void main(String[] args) {
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);
User user = app.getBean(User.class);
//调用业务方法
user.hello();
}
}
总结:Component和Bean都可以标识把对象交给spring容器管理
@Component/@Bean区别:
1.@component spring容器通过反射自动创建对象
@Bean 是用户自己手动创建的对象
2.@component 是标识类的
@Bean 标识配置类中的方法
3.@component 对象的Id是类名的首字母小写
@Bean 对象的Id是方法名
Spring中依赖注入
依赖注入就是将spring容器中管理对象,赋值给对象的属性
核心机制:如果需要使用依赖注入,则对象的属性必须有setXxx()方法
xml配置文件写法
(1)为普通属性赋值
1.定义类(类里必须有set方法)
package com.jt.demo7_di;
public class Person {
//定义属性
private Integer id;
private String name;
//依赖注入,为属性赋值,必须有set方法
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void sayHi(){
System.out.println("你好:"+id+":"+name);
}
}
2.在resources目录下配置xml文件spring_di.xml(依赖注入,通过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">
<!-- xml配置文件 为属性赋值 -->
<bean id="person" class="com.jt.demo7_di.Person">
<!-- 通过Bean的property属性为类的属性赋值 -->
<property name="id" value="100"/>
<property name="name" value="春节"/>
</bean>
</beans>
3.创建测试类,查看程序运行效果
public class TestPerson {
public static void main(String[] args) {
String resource = "spring_di.xml";
ApplicationContext app = new ClassPathXmlApplicationContext(resource);
Person person = app.getBean(Person.class);
person.sayHi();
}
}
(2)spring为对象赋值
1.定义Person类(类里必须有set方法)
package com.jt.demo7_di;
public class Person {
//定义属性
private Integer id;
private String name;
private Car car; //spring容器为属性赋值
//依赖注入,为属性赋值,必须有set方法
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void sayHi(){
System.out.println("你好:"+id+":"+name);
}
public void toGo(){
car.go();
}
}
2.在resources目录下配置xml文件spring_di.xml(依赖注入,通过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">
<!-- 1.让spring容器管理car -->
<bean id="car" class="com.jt.demo7_di.Car"></bean>
<!-- 2.xml配置文件,让spring管理Person,并且为属性赋值 -->
<bean id="person" class="com.jt.demo7_di.Person">
<!-- 通过Bean的property属性为类的普通属性赋值 -->
<property name="id" value="2100"/>
<property name="name" value="春节111"/>
<!-- 3.如果将对象赋值给属性,使用ref属性
ref:引用的id
相当于把spring管理的car对象传给person类的car属性,
实现松耦合-->
<property name="car" ref="car"/>
</bean>
</beans>
3.创建测试类,查看程序运行效果
package com.jt.demo7_di;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestPerson {
public static void main(String[] args) {
String resource = "spring_di.xml";
ApplicationContext app = new ClassPathXmlApplicationContext(resource);
Person person = app.getBean(Person.class);
person.sayHi();
person.toGo();
}
}