IOC容器
1. IOC基本概念:
- 控制反转(Inversion of Control,缩写为IoC)
- 使用IOC目的是为了降低耦合度
2. IOC底层原理
- xml解析、工厂模式、反射
3. IOC(接口)
1. BeanFactory:
IOC容器的基本实现,是Spring内部的使用接口,不提供开发人员进行使用。
区别:(加载配置文件时不创建对象,在获取对象(使用时)才创建对象)
2. ApplicationContext(一般用这种方式):
BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员使用。
区别:(加载配置文件时就会把配置文件对象进行创建)
3. IOC操作Bean管理
1. 什么是Bean管理
- Spring创建对象
- Spring注入属性
2. Spring 有两种类型的 bean
-
普通bean
:在配置文件中定义的bean
类型就是返回类型。(定义什么返回什么)-
创建类,创建配置文件
<!--创建类对象--> <bean id="mybean" class="com.wnaoii.spring5.factorybean.Mybean"></bean>
-
测试类测试
public class TestDemo { @Test public void testDemo() { ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml"); // 普通bean:创建什么类型返回什么类型 Mybean myBean = context.getBean("mybean",Mybean.class); System.out.println(myBean); } }
-
-
工厂bean(FactoryBean)
:在配置文件中定义的bean
类型可以和返回的类型不一样(多态?)- 创建类,让这个类作为工厂bean,实现接口 FactoryBean
- 实现接口里面的方法,在实现的方法中定义返回的bean类型
3. Bean管理的实现方式
1. 基于 xml 配置文件方式实现
-
创建对应的
bean.xml
文件中使用bean
标签,标签里添加对应的属性,即可实现对象的创建。 -
创建对象的时候也是默认执行无参构造器完成对象创建。
-
x 1<!--配置User对象创建-->2<bean id="user" class="com.wnaoii.User"/>
-
在Bean标签中有许多属性,这里介绍下常用属性
- id属性:唯一标识,在bean中生成对象的别名。
- class属性:类全路径(包类路径)
2. Bean管理 xml 方式(注入属性)
- xml 的注入方式也是通过get/set方法注入
-
使用
set
方法注入-
常规方式
public class Book { // 创建属性 private String bname; // 属性对应的set方法 public void setBname(String bname) { this.bname = bname; } public static void main(String[] args) { // 建对象 Book book = new Book(); // 注入值 book.setBname("xiaoming"); System.out.println(book.bname); } }
-
xml配置文件方式
-
写好xml配置文件
<!--配置User对象创建--> <bean id="book" class="com.wnaoii.Book"> <!-- 在bean标签中使用property完成属性注入 name:类里属性的名字 value:需要注入的值 --> <property name="bname" value="xiaoming"></property> </bean>
-
调用xml配置文件
public class TestSpring5 { @Test public void testAdd() { // 1.加载spring配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); // 2.获取配置创建的对象 Book book = context.getBean("book",Book.class); // getBean中”book“为xml配置的对象,Book.class表示转换的类型 book.pringtName(); System.out.println(book); } }
-
-
-
有参构造注入
-
常规方式
public class Book { // 创建属性 private String bname; public Book() { } // 有参构造 public Book(String bname) { this.bname = bname; } public static void main(String[] args) { // 建对象,有参构造注入值 Book book = new Book("xiaogang"); System.out.println(book.bname); } }
-
xml配置文件方式
-
创建类,定义属性,创建对应的有参构造器
public class orders { private String oname; private String address; // 无参构造不写也行? public orders() { } // 有参构造 public orders(String oname, String address) { this.oname = oname; this.address = address; } }
-
配置好xml配置文件里的Bean标签
<!-- 在bean标签中使用constructor-arg完成属性注入 name:类里属性的名字 value:需要注入的值 --> <bean id="orders" class="com.wnaoii.Orders"> <constructor-arg name="oname" value="手机"></constructor-arg> <constructor-arg name="address" value="中国"></constructor-arg> </bean>
-
测试类中测试
public class TestSpring5 { @Test public void testOrders() { // 1.加载spring配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml"); // 2.获取配置创建的对象 Orders orders = context.getBean("orders", Orders.class); orders.testOrders(); System.out.println(orders); } }
-
-
-
P名称空间注入(了解)
- 使用 p 名称空间注入,可以简化基于 xml 配置方式
3. Bean管理 xml 方式(注入其他类型属性)
1. 字面量
-
null 值
-
不注入值也为属性的值也为
null
,写了增加程序的可读性。大概? -
xml 配置文件中不设值添加
<null/>
标签<!--null值--> <property name="address"> <null/> </property>
-
address 属性中注入的值就设置为
null(空)
-
-
属性包含特殊符号
-
两种方法:
-
将特殊符号进行转义
<
>
,再注入。 -
将带特殊符号的内容写到CDATA
<!--注入"<<上海>>"这个值--> <property name="address"> <value><![CDATA[<<上海>>]]></value> </property>
-
-
4. Bean管理 xml 方式(注入外部Bean)
1. 注入属性-外部bean
-
创建两个类
service
类和dao
类-
service
类public class UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } }
-
dao
类public class UserDaoImp implements UserDao{ @Override public void update() { System.out.println("UserDao Update已运行!"); } }
-
-
在
service
调用dao
里面的方法public class UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void printUserService(){ // 调dao里的方法 userDao.update(); System.out.println("UserService已运行!"); } }
-
在Spring配置文件中进行配置
<!--配置User对象创建--> <bean id="userDao" class="com.wnaoii.dao.UserDaoImp"></bean> <bean id="userService" class="com.wnaoii.service.UserService"> <!-- 注入userDao对象 name属性:类里面属性的名称 ref:刚创建的userDao对象的bean标签的id值 --> <property name="userDao" ref="userDao"></property> </bean>
-
在测试类中测试
public class TestBean { @Test public void Test(){ // 1.加载spring配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("Bean2.xml"); // 2.获取配置文件中创建的对象 UserService userService = context.getBean("userService",UserService.class); userService.printUserService(); } }
2. 注入属性-内部Bean
-
一对多关系:部门和员工
- 一个部门包含多个员工
- 一个员工属于一个部门
-
在实体类中表示一对多的关系
-
部门类
// 部门类 public class Dept { private String dName; public void setdName(String dName) { this.dName = dName; } }
-
员工类
// 员工类 public class Emp { private String eName; private String gender; // 员工属于某一个部门,使用对象的形式表示 private Dept dept; public void setDept(Dept dept) { this.dept = dept; } public void seteName(String eName) { this.eName = eName; } public void setGender(String gender) { this.gender = gender; } }
-
-
在 spring 配置文件中进行配置
<!--员工类对象创建--> <bean id="emp" class="com.wnaoii.bean.Emp"> <!--设置两个普通的属性--> <property name="eName" value="小明"></property> <property name="gender" value="男"></property> <!--设置对象类型的属性--> <property name="dept"> <!--内部再嵌套一个对象--> <bean id="dept" class="com.wnaoii.bean.Dept"> <property name="dName" value="保安部"></property> </bean> </property> </bean>
3. 注入属性-级联赋值
-
和外部bean的区别就是在外部bean中赋值再传入
<!--级联赋值--> <bean id="emp" class="com.wnaoii.bean.Emp"> <!--设置两个普通的属性--> <property name="eName" value="小明"></property> <property name="gender" value="男"></property> <!--级联赋值--> <property name="dept" ref="dept"></property> </bean> <!--创建外部bean并赋值--> <bean id="dept" class="com.wnaoii.bean.Dept"> <property name="dName" value="财务部"></property> </bean>
5.Bean管理 xml 方式(注入集合类型属性)
1. 注入数组类型属性
-
在
xml
配置文件中创建对象 -
使用
<array>
标签注入<bean id="创建的对象名" class="类路径"> <property name="courses"> <array> <!--填写注入的值--> <value>注入的值</value> </array> </property> </bean>
2. 注入 List 集合类型属性
-
同上大同小异,List集合类型就用List标签注入
<bean id="创建的对象名" class="类路径"> <property name="courses"> <list> <!--填写注入的值--> <value>注入的值</value> </list> </property> </bean>
3. 注入 Map 集合类型
-
使用
<bean id="创建的对象名" class="类路径"> <property name="courses"> <map> <!--填写注入的值--> <entry key="" value=></entry> </map> </property> </bean>
4. 在集合里面设置对象类型值
(用上再看)
5. 把集合注入部分提取出来
-
使用util标签
<util:list id="list1"> <value>java</value> <value>python</value> <value>jsp</value> </util:list>
-
创建好后直接在xml配置文件创建的对象中应用
<bean id="student" class="com.wnaoii.spring5.collectiontype.student"> <property name="courses" ref="list1"></property> </bean>
6. 基于注解方式实现
-
什么是注解
- 注解是代码的特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值......)
- 使用注解,注解作用在类上面,方法上面,属性上面
- 注解的目的:简化 xml 配置
-
Spring
针对Bean
管理中创建对象提供的注解- @Conponent
- @Service
- @Controller
- @Repository
以上四个注解实现的功能是一样的,都可以用来创建Bean的实例,名称只是用来区分在哪个层
-
基于注解的方式创建对象
-
引入依赖
-
开启组件扫描
-
使用注解创建一定要配置开启扫描
-
在 xml 配置文件中开启
<context:component-scan base-package="com.wnaoii.spring5.testDemo"></context:component-scan>
-
base-package
的值是扫描的包路径,扫描的包可以添加逗号隔开,也可以扫描整个包路径。
-
-
创建对象
-
创建一个类的开头添加注解
@Service(value = "userServic") public class UserService { public void testDemo(){ System.out.println("testDemo运行中-----"); } }
- value的值就相当于xml配置文件中
<bean>
标签里的id值 - value的值不写默认为类名首字母小写
- value的值就相当于xml配置文件中
-
测试类中测试
public class TestDemo { @Test public void testService() { ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); UserService userServic = context.getBean("userServic", UserService.class); userServic.testDemo(); System.out.println(userServic); } }
-
-
-
基于注解的方式注入属性
-
常用的注入属性的注解
-
@AutoWired:根据属性类型进行自动装配
-
把 service 和 dao 对象创建,在 service 和 dao 类添加创建对象的注解
-
UserService
@Repository public class UserService { public void testDemo(){ System.out.println("testDemo运行中-----"); } }
-
UserDao
@Repository public class UserDaoImpl implements UserDao{ @Override public void add() { System.out.println("add方法正在运行-----"); } }
-
-
在 service 注入 dao 对象
-
在 service 类添加 dao 类型的属性,在属性上面使用注解
@Service(value = "userServic") @Repository public class UserService { // 定义dao类型属性 // 不需要添加set方法 // 添加注入属性注解 @Autowired private UserDao userDao; public void testDemo(){ System.out.println("testDemo运行中-----"); // 调dao里的方法 userDao.add(); } }
-
-
-
@Qualifier:根据属性名称进行注入
-
这个注解得和上面的
@AutoWired
注解一起使用 -
@AutoWired
注解根据类型注入,如果一个接口有多个实现类,@Qualifier
就能指定名称注入指定的实现类@Service(value = "userServic") @Repository public class UserService { @Autowired @Qualifier(value = "注入实现类的名称") // 根据名称注入 private UserDao userDao; public void testDemo(){ System.out.println("testDemo运行中-----"); // 调dao里的方法 userDao.add(); } }
-
-
@Resource:可以根据属性类型注入,也可以根据名称注入
-
根据类型注入
@Service(value = "userServic") @Repository public class UserService { // 和@AutoWired注解使用方法一致 @Resource private UserDao userDao; public void testDemo(){ System.out.println("testDemo运行中-----"); userDao.add(); } }
-
根据名称注入
@Service(value = "userServic") @Repository public class UserService { // 参考@Qualifier注解的使用,只不过value改为name @Resource(name = "userDaoImpl1") private UserDao userDao; public void testDemo(){ System.out.println("testDemo运行中-----"); userDao.add(); } }
-
@Resource
注解集合了@AutoWired
和@Qualifier
注解 -
@Resource
注解不是Spring官方包里的,是javax包中的,官方更推荐使用@AutoWired
和@Qualifier
注解
-
-
@Value:注入普通类型属性
-
在需要注入的地方上加上注解
@Value(value = "小名") private String name;
-
@Value
注解有点脱裤子放屁的感觉?直接赋值不香?
-
-
-
-
纯注解开发
-
创建配置类,替代 xml 配置文件
@Configuration
注解可以标识这个类为配置类@ComponentScan
注解代替xml配置文件的开启组件扫描
@Configuration // 设置为配置类,替代xml配置文件 @ComponentScan(basePackages = {"com.wnaoii"}) // 需要扫描包的路径 public class SpringConfig { }
-
编写测试类
AnnotationConfigApplicationContext
里的值是配置类的名称
public class TestDemo { @Test public void testService() { // 加载配置类 ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); UserService userServic = context.getBean("userServic", UserService.class); userServic.testDemo(); System.out.println(userServic); } }
-
4. Bean 的作用域
-
在 Spring 里面,默认创建单实例对象。(每次获取该对象都是同一地址)
-
在 Spring 里面,可以设置创建
bean
实例是单实例还是多实例(每次获取该对象都是不同的地址,创个新的)-
在 Spring 配置文件
bean
标签里面有属性scope
用于设置单实例还是多实例 -
scope
属性值(常用值)-
singleton(默认值):表示单实例对象,
-
prototype:表示多实例对象,
<!--添加 scope 属性值就是一个多实例对象--> <bean id="mybean" class="com.wnaoii.spring5.factorybean.Mybean" scope="prototype"></bean>
-
-
-
singleton
和prototype
的区别- scope值为
singleton
时,加载spring配置文件时就会创建对象 - scope值为
prototype
时,加载spring
配置文件时不会创建对象,在调用 getBean 方法的时候才创建多实例对象。
- scope值为
5. bean 生命周期
- 生命周期
- 从对象创建到对象销毁的过程
- bean 生命周期
- 通过构造器创建 bean 实例(无参构造)
- 为 bean 的属性设置值和对其他 bean 的应用(调用 set 方法)
- 调用 bean 的初始化的方法(需要进行配置初始化的方法)
- bean 可以使用了(获取到对象)
- 当容器关闭的时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
6. XML 自动装配
-
什么是自动装配
- 根据指定装配额规则(属性名称或者属性类型), Spring 自动将匹配的属性进行注入
-
使用
autowire
属性实现自动装配<bean id="emp" class="com.wnaoii.spring5.autowire.Emp" autowire="byName">
-
autowire属性常用值:
- byName:根据属性名称注入(注入值bean的id值要和类属性的名称一致)
- byType:根据属性类型注入