来源参考,b站狂神说:https://www.bilibili.com/video/BV1WE411d7Dv?spm_id_from=333.999.0.0
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
IOC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,
新版本的Spring也可以零配置实现IoC。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用
时再从Ioc容器中取出需要的对象。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.1.10.RELEASEversion>
dependency>
public class Hello {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("Hello,"+ name );
}
}
<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="hello" class="com.kuang.pojo.Hello">
<property name="name" value="Spring"/>
bean>
beans>
@Test
public void test(){
//解析beans.xml文件 , 生成管理相应的Bean对象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//getBean : 参数即为spring配置文件中bean的id .
Hello hello = (Hello) context.getBean("hello");
hello.show();
}
这个过程就叫控制反转 :
依赖注入 : 就是利用set方法来进行注入的
IOC是一种编程思想,由主动的编程变成被动的接收
我们不用再程序中去改动了 , 要实现不同的操作 , 只需要在xml配置文件中进行修改, 所谓的IoC,一句话搞定 : 对象由Spring 来创建 , 管理 , 装配 !
可以通过newClassPathXmlApplicationContext去浏览一下底层源码
public class User {
private String name;
public User() {
System.out.println("user无参构造方法");
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("name="+ name );
}
}
<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="user" class="com.kuang.pojo.User">
<property name="name" value="kuangshen"/>
bean>
beans>
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//在执行getBean的时候, user已经创建好了 , 通过无参构造
User user = (User) context.getBean("user");
//调用对象的方法 .
user.show();
}
public class UserT {
private String name;
public UserT(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("name="+ name );
}
}
<bean id="userT" class="com.kuang.pojo.User">
<constructor-arg index="0" value="kuangshen2"/>
bean>
<bean id="userT" class="com.kuang.pojo.User">
<constructor-arg name="name" value="kuangshen2"/>
bean>
<bean id="userT" class="com.kuang.pojo.User">
<constructor-arg type="java.lang.String" value="kuangshen2"/>
bean>
@Test
public void testT(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserT user = (UserT) context.getBean("user");
user.show();
}
alias 设置别名 , 为bean设置别名 , 可以设置多个别名
<alias name="userT" alias="userNew"/>
<bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
<property name="name" value="Spring"/>
bean>
<import resource="{path}/beans.xml"/>
上面的案例
要求被注入的属性 , 必须有set方法 , set方法的方法名由set + 属性首字母大写
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
// set和get方法自动生产,省略
// ...
<bean id="student" class="com.kuang.pojo.Student">
<property name="name" value="小明"/>
bean>
<bean id="addr" class="com.kuang.pojo.Address">
<property name="address" value="重庆"/>
bean>
<bean id="student" class="com.kuang.pojo.Student">
<property name="name" value="小明"/>
<property name="address" ref="addr"/>
bean>
<bean id="student" class="com.kuang.pojo.Student">
<property name="name" value="小明"/>
<property name="address" ref="addr"/>
<property name="books">
<array>
<value>西游记value>
<value>红楼梦value>
<value>水浒传value>
array>
property>
bean>
<property name="hobbys">
<list>
<value>听歌value>
<value>看电影value>
<value>爬山value>
list>
property>
<property name="card">
<map>
<entry key="中国邮政" value="456456456465456"/>
<entry key="建设" value="1456682255511"/>
map>
property>
<property name="games">
<set>
<value>LOLvalue>
<value>BOBvalue>
<value>COCvalue>
set>
property>
<property name="wife"><null/>property>
<property name="info">
<props>
<prop key="学号">20190604prop>
<prop key="性别">男prop>
<prop key="姓名">小明prop>
props>
property>
public class User {
private String name;
private int age;
}
导入约束 : xmlns:p="http://www.springframework.org/schema/p"
<bean id="user" class="com.kuang.pojo.User" p:name="狂神" p:age="18"/>
导入约束 : xmlns:c="http://www.springframework.org/schema/c"
<bean id="user" class="com.kuang.pojo.User" c:name="狂神" c:age="18"/>
在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,被称之为bean。简单地讲,
bean就是由IoC容器初始化、装配及管理的对象
<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton"/>
<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/>
<bean id="loginAction" class="com.foo.DefaultAccount" scope="request"/>
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
Spring中bean有三种装配机制,分别是:
Spring的自动装配需要从两个角度来实现,或者说是两个操作:
组件扫描和自动装配组合发挥巨大威力,使的显示的配置降低到最少。
推荐不使用自动装配xml配置 , 而使用注解 .
两个实体类,Cat Dog 都有一个叫的方法
新建一个用户类 User
编写Spring配置文件
autowire byName (按名称自动装配)
<bean id="user" class="com.kuang.pojo.User" autowire="byName">
<property name="str" value="qinjiang"/>
bean>
autowire byType (按类型自动装配)
使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一
的异常(一般都是默认单例的)
<bean id="user" class="com.kuang.pojo.User" autowire="byType">
<property name="str" value="qinjiang"/>
bean>
jdk1.5开始支持注解,spring2.5开始全面支持注解。
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
<context:annotation-config/>
public class User {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
}
Autowired(required=false) 说明: false,对象可以为null;true,对象必须存对象,不能为null。
//如果允许对象为null,设置required = false,默认为true
@Autowired(required = false)
private Cat cat;
@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Autowired
@Qualifier(value = "dog2")
private Dog dog;
public class User {
//如果允许对象为null,设置required = false,默认为true
@Resource(name = "cat2")
private Cat cat;
@Resource
private Dog dog;
private String str;
}
使用注解注入属性
@Component("user")
// 相当于配置文件中
public class User {
@Value("秦疆")
// 相当于配置文件中
public String name;
}
@Component("user")
public class User {
public String name;
@Value("秦疆")
public void setName(String name) {
this.name = name;
}
}
功能与@Component,看项目组习惯
singleton:默认的,Spring会采用单例模式创建这个对象。关闭工厂 ,所有的对象都会销毁。
@Controller("user")
@Scope("prototype")
public class User {
@Value("秦疆")
public String name;
}
JavaConfig 原来是 Spring 的一个子项目,它通过 Java 类的方式提供 Bean 的定义信息,在 Spring4 的版本, JavaConfig 已正式成为 Spring4 的核心功能 。
测试
@Component //将这个类标注为Spring的一个组件,放到容器中!
public class Dog {
public String name = "dog";
}
@Configuration //代表这是一个配置类
public class MyConfig {
@Bean //通过方法注册一个bean,这里的返回值就Bean的类型,方法名就是bean的id!
public Dog dog(){
return new Dog();
}
}
@Configuration //代表这是一个配置类
public class MyConfig2 {
}
@Configuration
@Import(MyConfig2.class) //导入合并其他配置类,类似于配置文件中的 inculde 标签
public class MyConfig {
@Bean
public Dog dog(){
return new Dog();
}
}