IOC容器
1、IOC底层原理
2、IOC接口(BeanFactory)
IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
Spring提供IOC容器实现两种方式:
-
BeanFactory:IOC容器基本实现,是Spring内部使用的接口,不提供给开发人员使用
加载配置文件时不会创建对象,在获取对象(使用)对象时才去创建对象
-
ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用
加载配置文件时就会把在配置文件时候就会把在配置文件对象进行创建
-
ApplicationContext接口实现类
- FileSystemXmlApplictionContext:加载本地XML文件
- ClassPathXmlApplictionContext:加载项目中的xml文件
3、IOC操作Bean管理(概念)
1、什么是Bean管理
Spring创建对象
Spring注入属性
2、Bean管理操作
- 基于xml配置文件方式实现
- 基于注解方式实现
4、IOC接口Bean管理(基于xml)
1、基于xml方式创建对象
- 在Spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
- 在bean标签中有许多属性,介绍常用的属性
- id属性:唯一标识
- class属性:类全路径(包类路径)
- 创建对象时会自动调用无参构造,完成对象的创建
2、基于xml方式注入属性
DI:依赖注入,就是注入属性,DI是IOC的一种实现方式
3、第一种注入方式:使用set方法进行注入
-
创建类,定义属性和对应的set方法
public class Book { private String name; private String city; public void setName(String name) { this.name = name; } public void setCity(String city) { this.city = city; } @Override public String toString() { return "Book{" + "name='" + name + '\'' + ", city='" + city + '\'' + '}'; } }
-
在spring配置文件配置对象创建,配置属性注入
<!--set方法注入--> <bean id="book" class="com.gdcp.Book"> <!--使用property完成属性注入 name:属性名称 value:注入的值 --> <property name="city" value="广东"></property> <property name="name" value="张三"></property> </bean>
4、第二种注入方式:使用有参构造器进行注入
-
创建类,并生成有参构造
-
public class Orders { private String username; private BigDecimal price; public void setUsername(String username) { this.username = username; } public void setPrice(BigDecimal price) { this.price = price; } public Orders(String username, BigDecimal price) { this.username = username; this.price = price; } @Override public String toString() { return "Orders{" + "username='" + username + '\'' + ", price=" + price + '}'; } }
-
在Spring配置文件中进行配置
<!--构造方法注入--> <bean id="orders" class="com.gdcp.Orders"> <constructor-arg name="username" value="张三"></constructor-arg> <constructor-arg name="price" value="1"></constructor-arg> </bean>
5、p名称空间注入(了解)可以简化基于xml配置方式
1、添加p名称空间在配置文件中
xmlns:p = "http://www.springframework.org/schema/p"
2、进行属性注入,在bean标签里面进行操作
<bean id="book" class="com.gdcp.Book" p:name="广东" p:city="张三"></bean>
6、IOC操作Bean管理(xml注入其他类型属性)
1、字面量
-
null值
<property name="address"> <null/> </property>
-
属性值包含特殊符号
<property name="address"> <value><![CDATA[<<南京>>]]></value> </property>
2、注入属性-外部bean
-
创建两个类service类和dao类
public class UserDaoImpl implements UserDao { @Override public void update() { System.out.println("userDaoImpl update"); } } public class UserService { public void add(){ System.out.println("UserService add....."); } }
-
在servic调用dao里面的方法
public class UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void add(){ System.out.println("UserService add....."); userDao.update(); } }
-
在xml配置文件中进行配置
<bean id="userService" class="com.gdcp.service.UserService"> <!--ref 属性:ref属性是在xml配置文件中所配置的bean的id--> <property name="userDao" ref="userDao"></property> </bean> <bean id="userDao" class="com.gdcp.dao.UserDaoImpl"></bean>
3、注入属性-内部bean和级联赋值
-
一对多关系:部门和员工
一个部门有多个员工,一个员工属于一个部门。部门是一,员工是多
-
在实体类之间表示一对多关系
//部门表 public class Dept { private String name; public void setName(String name) { this.name = name; } @Override public String toString() { return "Dept{" + "name='" + name + '\'' + '}'; } } //员工表 package com.gdcp.bean; public class Emp { private String name; private Dept dept; public void setName(String name) { this.name = name; } public void setDept(Dept dept) { this.dept = dept; } @Override public String toString() { return "Emp{" + "name='" + name + '\'' + ", dept=" + dept + '}'; } }
<!--内部bean--> <bean id="emp" class="com.gdcp.bean.Emp"> <property name="name" value="张三"></property> <property name="dept"> <bean id="dept" class="com.gdcp.bean.Dept"> <property name="name" value="销售部"></property> </bean> </property> </bean> <!--级联赋值 写法一 --> <bean id="emp" class="com.gdcp.bean.Emp"> <property name="name" value="张三"></property> <property name="dept" ref="edpt"></property> </bean> <bean id="edpt" class="com.gdcp.bean.Dept"> <property name="name" value="售后部"></property> </bean> <!--级联赋值 写法二 --> <bean id="emp" class="com.gdcp.bean.Emp"> <property name="name" value="张三"></property> <property name="dept" ref="edpt"></property> <property name="dept.name" value="开发部"></property> </bean> <bean id="edpt" class="com.gdcp.bean.Dept"> <property name="name" value="售后部"></property> </bean>
7、IOC操作Bean管理(xml注入集合)
1、注入数组类型属性
2、注入List集合类型属性
3、注入Map集合类型属性
创建类,并创建数组、list、map、set类型属性,并生成set方法
package com.gdcp.collectionType;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Stu {
//数据类型属性
private String[] courses;
//list类型属性
private List<String> list;
//Map类型属性
private Map<String,String> map;
//set类型属性
private Set<String> set;
public void setCourses(String[] courses) {
this.courses = courses;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setSet(Set<String> set) {
this.set = set;
}
@Override
public String toString() {
return "Stu{" +
"courses=" + Arrays.toString(courses) +
", list=" + list +
", map=" + map +
", set=" + set +
'}';
}
}
在xml配置文件中配置属性
<bean id="stu" class="com.gdcp.collectionType.Stu">
<property name="courses">
<array>
<value>Java程序设计基础</value>
<value>数据库应用</value>
</array>
</property>
<property name="list">
<list>
<value>张三</value>
<value>李四</value>
</list>
</property>
<property name="map">
<map>
<entry key="Java" value="java"></entry>
<entry key="PHP" value="php"></entry>
</map>
</property>
<property name="set">
<set>
<value>Mysql</value>
<value>Sql</value>
</set>
</property>
</bean>
4、在集合里面设置对象类型值
-
创建对象
<bean id="course1" class="com.gdcp.collectionType.Course"> <property name="name" value="Java"></property> </bean> <bean id="course2" class="com.gdcp.collectionType.Course"> <property name="name" value="Php"></property> </bean>
-
属性注入
<property name="courseList"> <list> <ref bean="course1"></ref> <ref bean="course2"></ref> </list> </property>
5、把集合注入部分提取出来
1、在srping配置文件中引入uitl命名空间
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
" >
2、使用util标签完成list集合注入提取
<property name="list" ref="bookList"></property>
<util:list id="bookList">
<value>Java</value>
<value>Php</value>
</util:list>
8、IOC操作Bean管理(FactoryBean)
1、Spring有两种Bean
- 一种普通Bean
- 另外一种工厂Bean(FactoryBean)
2、普通Bean
在Spring配置文件中定义的类型就是返回的类型
3、工厂Bean
在spring配置文件定义bean类型可以和返回类型不一样
第一步创建类,让这个类作为工厂bean,实现接口FactoryBean
第二步 实现接口里面的方法,在实现的方法中定义返回的bean类型
public class MyBean implements FactoryBean<Course> {
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setName("abc");
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return false;
}
}
@Test
public void testMyBean(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Course myBean = context.getBean("myBean", Course.class);
System.out.println(myBean);
}
<bean id="myBean" class="com.gdcp.collectionType.MyBean"></bean>
9、IOC操作Bean管理(Bean作用域)
1、在Spring里面,设置创建bean实例是单实例还是多实例
2、在Spring里面,默认情况下,bean是单实例对象
@Test
public void testMyBean(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Course myBean1 = context.getBean("myBean", Course.class);
Course myBean2 = context.getBean("myBean", Course.class);
System.out.println(myBean1);//com.gdcp.collectionType.Course@2698dc7
System.out.println(myBean2);//com.gdcp.collectionType.Course@2698dc7
}
3、如何设置单实例还是多实例
-
在spring配置文件bean标签中的scope属性用于设置单实例还是多实例
-
scope属性值
默认值为singletion 表示单实例对象
prototype 表示多实例对象
-
singleton和prototype区别
- 设置scope值为singleton时候,加载spring配置文件时候就会创建单实例对象
- scope值为prototype时候,不是在加载spring配置文件时候创建对象,而是在getBean方法调用时创建多实例对象
10、IOC操作Bean管理(bean生命周期)
1、生命周期
对象创建到对象销毁的过程
2、bean生命周期
- 通过构造器创建bean实例(无参构造)
- 为bean的属性设置值和对其他bean的引用
- 调用bean的初始化方法(需要进行配置)
- bean可以使用(对象获取到了)
- 当容器关闭时候,调用bean的销毁方法(需要进行配置销毁方法)
11、IOC操作Bean管理(xml自动装配)
1、什么时自动装配
- 根据指定装配规则(属性名称或者属性类型),Spring 自动将匹配的属性值进行注入
2、演示自动装配过程
<!--
autowire : byName 会根据当前对象所对象的属性名找到bean中id相同的进行配置
byType 根据当前对象的类型在bean中找到相同的类型进行配置
-->
<bean id="emp" class="com.gdcp.auto.Emp" autowire="byName"></bean>
<bean id="dept" class="com.gdcp.auto.Dept"></bean>
12、IOC操作Bean管理(外部属性文件)
-
直接配置数据库信息
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.mysql.jdcc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/userDb"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </bean>
-
引入外部属性文件配置数据库连接池
-
引入命名空间
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xmlns:context ="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd " >
-
创建外部配置文件,properties格式文件,写数据库信息
prop.driverClass = com.mysql.jdbc.Driver prop.url = jdbc:mysql://localhost:3306/UserDb prop.username = root prop.password = root
-
把外部properties属性文件引入到spring配置文件中
<context:property-placeholder location="jdbc.properties"/> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${prop.driverClass}"></property> <property name="url" value="${prop.url}"></property> <property name="username" value="${prop.username}"></property> <property name="password" value="${prop.password}"></property> </bean>
-
13、IOC操作Bean管理(基于注解)
1、什么是注解
- 注解是代码特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值)
- 使用注解,注解作用在类上面,方法上面,属性上面
- 使用注解的目的:简化xml配置
2、Spring针对Bean管理中创建对象提供注解
- @Component
- @Service
- @Controller
- @Repository
以上是个注解功能是一样的,都可以用来创建bean实例
3、基于注解方式实现对象创建
- 引入依赖(AOP)
- 开启组件扫描
<context:component-scan base-package="com.gdcp"></context:component-scan>
-
创建类,在类上面添加创建对象注解
@Component(value = "userService") public class UserService { public void add(){ System.out.println("service add...."); } }
-
开启组件扫描细节配置
<!-- use-default-filters 为false时不去使用默认规则进行扫码,而是通过自定义扫描情况进行扫描 type为annotation是通过注解扫描expression中是指向的类型 --> <context:component-scan base-package="com.gdcp" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!-- 使用默认的扫描规则进行扫描,并不扫描exclude-filter的类型 --> <context:component-scan base-package="com.gdcp" > <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/> </context:component-scan>
-
基于注入方式实现属性注入
-
@AutoWired:根据属性类型进行自动装配
-
第一步把service和dao对象创建,在service和dao类添加创建对象注解
-
第二步在service注入dao对象,在service类添加dao类型属性,在属性上使用注解
@Service public class UserService { @Autowired private UserDao userDao; public void add(){ System.out.println("service add...."); userDao.update(); } }
-
-
@Qualifier:根据属性名称进行注入
-
@Qualifier注解使用时必须和@AutoWired一起使用
@Service public class UserService { @Autowired @Qualifier(value = "userDaoImpl") private UserDao userDao; public void add(){ System.out.println("service add...."); userDao.update(); } }
-
-
@Resource:可以根据类型注入或者根据名称注入
// @Resource @Resource(name = "userDaoImpl") private UserDao userDao; public void add(){ System.out.println("service add...."); userDao.update(); }
-
@Value:注入普通类型属性
@Value("张三") private String userName;
-
-
完全注解开发
-
创建配置类,替代xml配置文件
@Configuration @ComponentScan(basePackages = {"com.gdcp"}) public class SpringConfig { }
-
编写测试类
@Test public void testUserService2(){ ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); UserService userService = context.getBean("userService", UserService.class); userService.add(); System.out.println(userService); }
-