当前位置: 首页> 教育> 就业 > Spring之IOC

Spring之IOC

时间:2025/7/28 1:39:01来源:https://blog.csdn.net/still_five_Days/article/details/139451423 浏览次数:0次
<?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:p="http://www.springframework.org/schema/p"xmlns:c="http://www.springframework.org/schema/c"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!--  注册一个Cat对象--><bean class="com.zsc.pojo.Cat" id="cat" p:nick="花花" p:color="黑色"/><bean class="com.zsc.pojo.UserBean" id="user"><!-- 设值注入 --><property name="cat" ref="cat"><!--<bean class="com.zsc.pojo.Cat" />--></property><property name="favorites"><array><value>篮球</value><value>爬山</value><value>逛街</value></array></property><property name="cats"><list><bean class="com.zsc.pojo.Cat" p:nick="小花1" p:color="红色"/><bean class="com.zsc.pojo.Cat" p:nick="小花2" p:color="绿色"/><bean class="com.zsc.pojo.Cat" p:nick="小花3" p:color="黄色"/></list></property><property name="map" ><map><entry key="name1" value="张三1"/><entry key="name2" value="张三2"/><entry key="name3" value="张三3"/></map></property><property name="props"><props><prop key="username" >root</prop><prop key="password">123</prop></props></property></bean>
</beans>

1. IOC控制反转

IOC本质上是一个概念,是一种思想,控制反转就是对对象控制权的转移,SpringIOC容器创建对象,然后把对象的使用权交出去

2. 基于XML配置文件方式实现

2.1 基本使用

a.引入依赖

<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.17.RELEASE</version></dependency><!-- https://mvnrepository.com/artifact/junit/junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency></dependencies>

b. 添加spring的配置文件

<?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"></beans>

c.注册Bean

将需要被Ioc容器管理的类型通过<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 class="com.gupaoedu.pojo.UserBean" />
</beans>

d.测试获取

/*** IoC的方式获取 UserBean 对象*/
@Test
public void fun2(){// 1.IoC容器的初始化操作 调用UserBean中无参构造器创建对象ApplicationContext ac =new ClassPathXmlApplicationContext("applicationContext.xml");// 2.从容器中获取UserBean对象 没有显示的newUserBean user = (UserBean) ac.getBean("userBean");user.say();
}

2.2 从容器中获取对象的方式

2.2.1 根据ID

id只能声明一个

2.2.2 根据name

可以声明一个或者多个

<?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="com.zsc.pojo.UserBean" id="userBean" name="userBean2"/>--><bean class="com.zsc.pojo.UserBean" id="user1,user2,user3" name="u1,u2,u3"/>
</beans>

 id="user1,user2,user3" 只表示一个

name="u1,u2,u3" 表示会被拆分为3个name属性【拆分会根据 ',' ';' ' ' 空格 】

2.2.3 根据类型 

我们可以根据需要获取的对象的类型从容器中获取对象

@Test
public void fun6(){ApplicationContext ac =new ClassPathXmlApplicationContext("applicationContext.xml");UserBean bean = ac.getBean(UserBean.class);bean.say();
}

如果同一类型的对象在容器中有多个,我们仅仅只是通过类型来查找,那么就会报错

<?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="com.gupaoedu.pojo.UserBean" id="userBean" name="userBean2"/>--><bean class="com.gupaoedu.pojo.UserBean" id="user1,user2,user3" name="u1 u2 u3"/><bean class="com.gupaoedu.pojo.UserBean" id="userBean1" name="ub1"/>
</beans>

那么怎么解决呢?在getBean方法中通过组合条件来查找

@Test
public void fun6(){ApplicationContext ac =new ClassPathXmlApplicationContext("applicationContext.xml");// UserBean bean = ac.getBean(UserBean.class);UserBean bean = ac.getBean("u1",UserBean.class);bean.say();
}

 还要就是我们可以在<bean>中设置primary属性为true,那么当同一类型有多个对象时,就会优先返回primary属性的对象

2.3 BeanFactory和ApplicationContext的区别

 /*** ApplicationContext*    默认在IoC容器初始化的时候就会实例化对象*/@Testpublic void fun1(){ApplicationContext ac =new ClassPathXmlApplicationContext("applicationContext.xml");}/*** BeanFactory*    IoC容器初始化的时候不会实例化对象*    在调用获取的时候才会创建对象*/@Testpublic void fun2(){BeanFactory factory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));factory.getBean("u1");}

类图:

 

 从类图上我们可以很清晰的看到ApplicationContext具有BeanFactory的所有功能,同时扩展了很多BeanFactory不具备的功能(如事件广播,资源加载,web支持等等...)

2.4 工厂注入

2.4.1 静态工厂注入

<?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="com.zsc.factory.StaticFactoryDemo" factory-method="getInstance" id="user"></bean></beans>
 public static Map<String,UserBean> hashMap ;static {hashMap = new HashMap<String, UserBean>();hashMap.put("a1",new UserBean());hashMap.put("a2",new UserBean());hashMap.put("a3",new UserBean());}/*** 静态工厂提供的方法* @return*/public static UserBean getInstance(){return hashMap.get("a1");}

 2.4.2 动态工厂注入

public class DynamicFactoryDemo {public UserBean getInstance(){return new UserBean();}
}
?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="com.zsc.factory.DynamicFactoryDemo" id="dynamicFactoryDemo" ></bean><!--  从工厂对象中获取 需要的对象--><bean id="user2" factory-bean="dynamicFactoryDemo" factory-method="getInstance"/></beans>

2.5 属性注入 

属性注入主要是指如何给对象中的属性赋值

2.5.1 构造注入

通过构造方法注入,首先得提供对应得构造方法,既可以通过name也可以通过index来指定要赋值得参数

<?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="com.zsc.pojo.UserBean" id="user"><!-- 构造注入 --><!--<constructor-arg name="id" value="666"/><constructor-arg name="userName" value="bobo"/>--><constructor-arg index="0" value="999" /><constructor-arg index="1" value="gp" /></bean>
</beans>

 2.5.2 设值注入

注入的属性必须提供对应的setter方法

<bean class="com.gupaoedu.pojo.UserBean" id="user1"><!-- 设值注入 --><property name="id" value="1"/><property name="userName" value="张三"/>
</bean>

 2.5.3 其它注入类型

private Cat cat;private String[] favorites;private List<Cat> cats;private Map<String,Object> map;private Properties props;

3. 基于Java配置的实现方式

springboot流行之后,java配置的方式开始被广泛使用

java配置类

@Configuration
public class JavaConfig {/*** @Bean 作用和我们在applicationContext.xml中添加的<bean> 效果一样</>* 默认的name是方法名称* 自定义的name 可以通过value属性或者name属性来指定* @return*/@Bean(name = {"aaa","bbb"})public User getUser(){User user = new User();//user.set....return user;}
}

测试

public class MainTest1 {@Testpublic void fun1(){// 通过@Configuraction注解来初始化IoC容器ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);System.out.println(ac.getBean("aaa",User.class));}
}

4.注解编程

4.1 配置注解

4.2 赋值注解

4.3 注解编程的使用

 我们需要将被IOC容器管理的类型通过@Component注解标注

@Component // 需要被IoC容器加载
public class UserController {@Autowiredprivate IUserService service;public List<User> query(){return service.query();}
}

 @Autowired和@Resource的区别

@Autowired:默认只能根据类型来查找,可以结合@Qualifier("abc")注解来实现通过name查找

@Resource:默认同样是根据类型来查找,但是提供的有type和name属性类实现不同的查找方式

 4.3.1 基于java配置类的方式

我们需要在Java配置类中通过@ComponentScan注解来指定扫描的路径

默认的情况下扫描的是当前路径及其子路径下的所有被@Component @Comtroller @Service @Repository标注的类型

@Configuration
@ComponentScans({@ComponentScan(value = {"com.zsc.controller"},useDefaultFilters = false,includeFilters = {@ComponentScan.Filter(Controller.class)}),@ComponentScan(value = {"com.zsc.service","com.zsc.dao"},useDefaultFilters = true,excludeFilters = {@ComponentScan.Filter(Controller.class)})
})
public class JavaConfig {}

4.3.2 @Value注解介绍

@value帮助我们给数组动态的设值

@Component
@Data
public class User {@Value("bobo") // 注入普通的字符串private String userName ;@Value("#{systemProperties['os.name']}")private String systemPropertiesName; // 注入操作系统的信息@Value("#{T(java.lang.Math).random()*100}")private double randomNumber; // 注入表达式的结果@Value("#{person.personName}")private String fromPersonName; // 注入其他Bean的属性@Value("classpath:test.txt")private Resource resourceFile;@Value("http://www.baidu.com")private Resource baiduFile;
}
@Component
@Data
public class Person {@Value("PersonInfo")private String personName;
}

java配置类

@Configuration
@ComponentScan("com.zsc")
public class JavaConfig {}

测试

public static void main(String[] args) {ApplicationContext ac = new AnnotationConfigApplicationContext(JavaConfig.class);System.out.println(ac.getBean(User.class));User user = ac.getBean(User.class);}

若需要读取第三方的properties文件中的信息

创建第三方文件,在java配置类中通过@PropertySource注解来显示引入属性文件

@Configuration
@ComponentScan("com.zsc")
// 显示的指定要加载的属性文件
@PropertySource({"classpath:spring-db.properties"})
public class JavaConfig {}

 4.3.3 @PostContruct @PreDestroy @DependsOn

@PostConstruct 系统初始化完成后的回调方法

@PreDestroy 系统销毁时的回调方法

@DependsOn 指定实例化对象的先后顺序

@Component
@DependsOn({"user"}) // Person的实例化依赖于User对象的实例化,也就是User先于Person实例化
public class Person {public Person(){System.out.println("Person 构造方法执行了...");}
}

 4.3.4 @Import注解

将类型加入到IOC容器中的方式有哪些

1.基于XML文件的方式<bean >

2.基于XML文件的方式context:Component-Scan + @Component

3.基于Java配置类@Bean

4.基于Java配置类@ComponentScan + @Component

5.FactoryBean + getObject方法

6.@Import

4.3.4.1 静态使用

直接在@Import注解中直接定义要引入到IOC容器中的类型

缺点:  无法灵活的指定引入的类型

4.3.4.2 动态使用-ImportSelector

通过重写selectImports方法来达到灵活控制引入类型的目的

public class GpImportSelector implements ImportSelector {/**** @param annotationMetadata* @return*    IoC 要加载的类型的全路径的字符串数组*/public String[] selectImports(AnnotationMetadata annotationMetadata) {// 在此处实现不同的业务逻辑控制return new String[]{LoggerService.class.getName(),CacheService.class.getName()};}
}
 4.3.4.3 动态使用-ImportBeanDefinitionRegistrar
public class GpImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {/**** @param annotationMetadata* @param beanDefinitionRegistry IoC容器中管理对象的一个注册器*/public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {// 需要将添加的对象包装为一个RootBeanDefinition对象RootBeanDefinition cache = new RootBeanDefinition(CacheService.class);beanDefinitionRegistry.registerBeanDefinition("cache",cache);RootBeanDefinition logger = new RootBeanDefinition(LoggerService.class);beanDefinitionRegistry.registerBeanDefinition("logger",logger);}
}

5.Bead对象的作用域

默认的情况是singleton

@Bean
@Scope("prototype")
public Person person(){return new Person();
}@Bean
@Scope("prototype")
public Person person(){return new Person();
}
@Bean
@Scope("singleton")
public Person person(){return new Person();
}

 6. 总结

        本文主要介绍了SPring IOC的简单使用,Bean XML配置方式的对象获取以及DI注入,随着技术的发展,注解编程成为了时代的潮流,于是又介绍了注解结合java配置类的使用怎么更加灵活的获取对象以及属性注入的方式,最后介绍了Bean对象的作用域。对Spring的IOC有了初步的认识

关键字:Spring之IOC

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: