控制反转IoC(Inversion of Control),是一种设计思想,是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建和组装对象(Bean)存入容器中,程序使用时再从Ioc容器中取出需要的对象。
之前的业务中,用户的需求会影响原来的代码,需要根据用户的需求去修改源代码。
使用一个Set接口实现,发生革命性的变化。
private UserDao userDao;
//利用set进行动态实现值的注入
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
- 之前,程序使主动创建对象,控制权在程序猿手上
- 使用set注入之后,程序不再具有主动性,变成了被动的接受对象
注入思想,从本质上解决了问题,程序员不用再去管理对象的创建了,降低了系统的耦合度。这是IOC的原型
二、通过IOC编写程序的步骤-
编写一个实体类
package com.zyx.pojo; public class Hello { private String str; public Hello() { } public Hello(String str) { this.str = str; } public String getStr() { return str; } public void setStr(String str) { this.str = str; } @Override public String toString() { return "hello{" + "str='" + str + '\'' + '}'; } }
-
编写配置文件,applicationContext.xml
<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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="hello" class="com.zyx.pojo.Hello"> <property name="str" value="Spring"/> bean> beans>
-
测试
public class MyTest { public static void main(String[] args) { //获取ApplicationContext:拿到Spring容器 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //我们的对象现在都在Spring中管理,要使用直接去里面取出来就可以 //getBean : 参数即为spring配置文件中bean的id . Hello hello = (Hello) context.getBean("hello"); System.out.println(hello.toString()); } }
-
Hello 对象是谁创建的 ? 【hello 对象是由Spring创建的】
-
Hello 对象的属性是怎么设置的 ? 【 hello 对象的属性是由Spring容器设置的】
-
控制:传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的
-
反转:程序本身不创建对象 , 而变成被动的接收对象 .
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
beans>
3.1 别名
alias 设置别名 , 为bean设置别名 , 可以设置多个别名
<alias name="userT" alias="userNew"/>
3.2 import
团队的合作通过import来实现 .
<import resource="{path}/applicationContext.xml"/>
3.3 Bean的配置
在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,被称之为bean,就是java对象。简单地讲,bean就是由IoC容器初始化、装配及管理的对象。
类型 变量名 = new 类型();
Hello hello = new Hello();
id = 变量名, 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
3.3.2 name如果配置id,又配置了name,那么name是别名
name可以设置多个别名,可以用逗号,分号,空格隔开
如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;
bean 对象所对应的全限定名:包名 + 类型
3.3.4 propertyproperty相当于给对象中的属性设置一个值
- ref:引用Spring容器中创建好的对象
- value:具体的值,基本数据类型
<bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
<property name="name" value="Spring"/>
bean>
3.3.5 scope(Bean的作用域)
-
单例模式(Spring默认机制)
<bean id="user" class="com.zyx.pojo.User" scope="singleton"/>
-
原型模式:每次从容器种get的时候,都会产生一个新对象
<bean id="user" class="com.zyx.pojo.User" scope="prototype"/>
-
Request(基于web的应用中使用)
-
Session(基于web的应用中使用)
-
依赖注入
-
依赖:bean对象的创建依赖于容器
-
注入:bean对象中的所有属性,由容器来注入
-
POJO得有有参构造,通过有参构造方法来创建
- 实体类
public class User {
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 );
}
}
-
编写配置文件,applicationContext.xml
- 下标赋值
<bean id="user" class="com.zyx.pojo.User"> <constructor-arg index="0" value="xue"/> bean>
- 类型赋值(不建议使用)
<bean id="user" class="com.zyx.pojo.User"> <constructor-arg type="java.lang.String" value="xue"/> bean>
- 参数名(推荐使用)
<bean id="user" class="com.zyx.pojo.User"> <constructor-arg name="name" value="xue"/> bean>
-
测试
@Test public void testT(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserT user = (UserT) context.getBean("user"); user.show(); }
要求被注入的属性 , 必须有set方法 , set方法的方法名由set + 属性首字母大写 , 如果属性是boolean类型 , 没有set方法 , 是 is .
Set注入是指IoC容器通过成员变量的setter方法来注入被依赖对象。这种注入方式简单、直观,因而在Spring的依赖注入里大量使用。
-
编写pojo类
package com.zyx.pojo; public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
package com.zyx.pojo; import java.util.*; public class Student { private String name; private Address address; private String[] book; private List<String> hobbys; private Map<String, String> card; private Set<String> games; private String wife; private Properties info; }
-
编写配置文件,applicationContext.xml
<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 https://www.springframework.org/schema/beans/spring-beans.xsd"> beans>
- 常量注入
<bean id="student" class="com.zyx.pojo.Student"> <property name="name" value="xue"/> bean>
-
Bean注入
注意点:这里的值是一个引用,ref
<bean id="address" class="com.zyx.pojo.Address"> <property name="address" value="重庆"/> bean> <bean id="student" class="com.zyx.pojo.Student"> <property name="name" value="xue"/> <property name="address" ref="address"/> bean>
-
数组注入
<bean id="student" class="com.zyx.pojo.Student"> <property name="name" value="xue"/> <property name="address" ref="address"/> <property name="book"> <array> <value>红楼梦value> <value>西游记value> <value>水浒传value> array> property> bean>
-
List注入
<property name="hobbys"> <list> <value>听歌value> <value>敲代码value> <value>看电影value> list> property>
-
Map注入
<property name="card"> <map> <entry key="身份z" value="1234444444444"/> <entry key="yhk" value="1234444444444"/> map> property>
-
set注入
<property name="games"> <set> <value>LOLvalue> <value>BOBvalue> <value>COCvalue> set> property>
-
Null注入
<property name="wife"> <null/> property>
-
Properties注入
<property name="info"> <props> <prop key="学号">20190515prop> <prop key="性别">男prop> <prop key="姓名">小明prop> props> property>
-
测试类
import com.zyx.pojo.Student; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.getAddress()); } }
public class User {
private String name;
private int age;
}
1、P命名空间注入 : 需要在头文件中加入约束文件
导入约束 : xmlns:p="http://www.springframework.org/schema/p"
<bean id="user" class="com.zyx.pojo.User" p:name="xue" p:age="18"/>
2、c 命名空间注入 : 需要在头文件中加入约束文件
c 就是所谓的构造器注入,需要把有参构造方法加上。
导入约束 : xmlns:c="http://www.springframework.org/schema/c"
<bean id="user2" class="com.zyx.pojo.User" c:name="xue" c:age="18"/>
五、Bean的自动装配【重点】
感觉就是自动注入属性
- 自动装配是Spring满足bean依赖一种方式!
- Spring会在上下文中自动寻找,并自动给bean装配属性!
Spring中bean有三种装配机制,分别是:
- 在xml中显示的配置
- 在java中显示配置
- 隐式的自动装配Bean【重要】
Spring的自动装配需要从两个角度来实现,或者说是两个 *** 作:
- 组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;
- 自动装配(autowiring):spring自动满足bean之间的依赖,也就是我们说的IoC/DI;
-
编写实体类
public class Cat { public String cat; public void shut(){ System.out.println("miao"); } @Override public String toString() { return "Cat{" + "cat='" + cat + '\'' + '}'; } }
public class Dog { public String dog; public void shut(){ System.out.println("wang"); } @Override public String toString() { return "Dog{" + "dog='" + dog + '\'' + '}'; } }
public class People { private Cat cat; private Dog dog; private String name; public People() { } public People(Cat cat, Dog dog, String name) { this.cat = cat; this.dog = dog; this.name = name; } public Cat getCat() { return cat; } public void setCat(Cat cat) { this.cat = cat; } public Dog getDog() { return dog; } public void setDog(Dog dog) { this.dog = dog; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "People{" + "cat=" + cat + ", dog=" + dog + ", name='" + name + '\'' + '}'; } }
-
编写Spring配置文件
<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="dog" class="com.zyx.pojo.Dog"/> <bean id="cat" class="com.zyx.pojo.Cat"/> <bean id="people" class="com.zyx.pojo.People"> <property name="cat" ref="cat"/> <property name="dog" ref="dog"/> <property name="str" value="xue"/> bean> beans>
-
测试
public class MyTest { @Test public void testMethodAutowire() { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); People people = (People) context.getBean("people"); people.getCat().shut(); people.getDog().shut(); } }
autowire byName (按名称自动装配)
修改bean配置,增加一个属性 autowire=“byName”
<bean id="cat" class="com.zyx.pojo.Cat"/>
<bean id="dog" class="com.zyx.pojo.Dog"/>
<bean id="people" class="com.zyx.pojo.People" autowire="byName">
<property name="name" value="xue"/>
bean>
小结:
当一个bean节点带有 autowire="byName"的属性时。
- 将查找class表示的类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。
- 去spring容器中寻找是否有此字符串名称id的bean对象。
- 如果有,就取出注入;如果没有,就报空指针异常。
autowire byType (按类型自动装配)
使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。
修改bean配置,增加一个属性 autowire=“byType”
<bean id="cat" class="com.zyx.pojo.Cat"/>
<bean id="dog" class="com.zyx.pojo.Dog"/>
<bean id="people" class="com.zyx.pojo.People" autowire="byType">
<property name="name" value="xue"/>
bean>
小结:
- byname的时候,需要保证所有的bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致
- byType的时候,需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性的类型一致
jdk1.5 支持的注解,spring2.5就支持注解了
要使用注解须知:
-
在spring配置文件中引入context文件头
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/
<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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> beans>
- @Autowired是按类型自动装配的,不支持id匹配。
- 直接在属性上使用@Autowired注解
- 需要导入 spring-aop的包!
- @Autowired(required=false) 说明:false,对象可以为null;true,对象必须存对象,不能为null。
//如果允许对象为null,设置required = false,默认为true
@Autowired(required = false)
private Cat cat;
5.3.2 @Qualifier(value=“id”)
- 和@Autowired一起使用,@Qualifier不能单独使用。
- @Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配
@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Autowired
@Qualifier(value = "dog2")
private Dog dog;
5.3.3 @Resource
- @Resource如有指定的name属性,先按该属性进行byName方式查找装配;
- 其次再进行默认的byName方式进行装配;
- 如果以上都不成功,则按byType的方式自动装配。
- 都不成功,则报异常。
- @Autowired与@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。
- @Autowired 通过 bytype的方式实现,而且必须要求这个对象存在【常用】。如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名
- @Resource默认通过 byname的方式实现,如果找不到名字,则通过 bytype的方式实现,如果两个都找不到,就报错【常用】
- 执行顺序不同。@Autowired先byType,@Resource先byName。
在spring4之后,要使用注解开发,需要导入aop的包
使用注解需要导入context约束,增加注解支持
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
beans>
6.1 Bean的实现
之前都是使用 bean 的标签进行bean注入,但是实际开发中一般都会使用注解
1、配置扫描哪些包下的注解
<context:component-scan base-package="com.zyx.pojo"/>
2、在指定包下编写类,增加注解
@Component("user")
// 相当于配置文件中
public class User {
public String name = "xue";
}
3、测试
@Test
public void test(){
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("beans.xml");
User user = (User) applicationContext.getBean("user");
System.out.println(user.name);
}
6.1.1 @Component三个衍生注解
@Component有几个衍生注解,在web开发中,会按照mvc三层架构分层!
- @Controller:web层
- @Service:service层
- @Repository:dao层
这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配Bean
6.2 普通属性注入使用注解注入属性
1、可以不用提供set方法,直接在直接名上添加@value(“值”)
@Component("user")
// 相当于配置文件中
public class User {
// 相当于配置文件中
@Value("xue")
public String name;
}
2、如果提供了set方法,在set方法上添加@value(“值”);
@Component("user")
public class User {
public String name;
@Value("秦疆")
public void setName(String name) {
this.name = name;
}
}
6.3 自动装配
-
@Autowired:自动装配,通过类型
如果Autowired不能唯一自动装配上属性,则需通过@Qualifier(value=“xxx”)
-
@Nullable:字段标记了这个注解,说明这个字段可以为Null
-
@Resource:自动装配,通过名字、类型
- 单例模式:@Scope(“singleton”):默认的,Spring会采用单例模式创建这个对象。关闭工厂 ,所有的对象都会销毁。
- 原型模式:@Scope(“prototype”):多例模式。关闭工厂 ,所有的对象不会销毁。内部的垃圾回收机制会回收
xml与注解:
- xml更加万能,适用于任何场合,维护更加简单
- 注解不是自己类是用不了,维护相对复杂
xml与注解的最佳实践
- xml用来管理bean
- 注解只负责完成属性的注入
- 我们在使用的过程中,只需要注意一个问题:必须要让注解生效,需要开启注解的支持
- 使用过程中, 可以不用扫描,扫描是为了类上的注解
<context:annotation-config/>
作用:
- 进行注解驱动注册,从而使注解生效
- 用于激活那些已经在spring容器里注册过的bean上面的注解,也就是显示的向Spring注册
- 如果不扫描包,就需要手动配置bean
- 如果不加注解驱动,则注入的值为null!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)