什么是IOC?
IOC 容器具有依赖注入功能的容器,它可以创建对象,IOC 容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。通常new一个实例,控制权由程序员控制,而"控制反转"是指new实例工作不由程序员来做而是交给Spring容器来做。在Spring中BeanFactory是IOC容器的实际代表者。
原理
xml解析,工厂模式,反射
小结:IOC就是将Bean(对象)的创建和管理交给Spring,通过1.解析xml获取类名和属性方法 2.通过反射获取类 3. newInstance获取Bean实例。
IOC操作Bean管理
基础配置:
pom.xml(拷贝不能直接用,这里还有其他几个子项目)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.spring</groupId>
<artifactId>spring-study</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>spring-ioc</module>
<module>spring-DI</module>
<module>spring-Autowire</module>
<module>spring-Autowire-ByAnnotation</module>
<module>spring-annotation</module>
<module>spring-proxy</module>
<module>spring-AOP</module>
<module>spring-JdbcTemplate</module>
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
</dependencies>
</project>
一、基于XML方式
名词解释:
DI:依赖注入,就是注入属性。
注入属性的两种方式:
1、使用(无参构造器创建对象)set 方法注入
pojo:User.java
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("name="+name);
}
}
beans.xml
<?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 id="user" class="com.spring.pojo.User">
<property name="name" value="sztestname"/>
</bean>
</beans>
测试
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = context.getBean("user", User.class);
System.out.println(user);
2、使用有参构造器注入(不需要set get方法)
UserT.java
package com.spring.pojo;
public class UserT {
String name;
public UserT(String name){
this.name=name;
}
@Override
public String toString() {
return "UserT{" +
"name='" + name + '\'' +
'}';
}
}
beans.xml(有参构造器,三种注入属性的方法 1.根据参数索引2.根据参数名字<常用> 3.根据参数类型)
<!--第一种 根据参数索引设置对象属性-->
<bean id="userT1" class="com.spring.pojo.UserT">
<constructor-arg index="0" value="根据参数索引的参数名字"/>
</bean>
<!--第二种,根据参数名字设置对象属性-->
<bean id="userT2" class="com.spring.pojo.UserT">
<constructor-arg name="name" value="根据参数名字的参数名字"/>
</bean>
<!-- 第三种 根据参数类型设置对象属性-->
<bean id="userT3" class="com.spring.pojo.UserT">
<constructor-arg type="java.lang.String" value="根据参数类型的参数名字"/>
</bean>
另外,多个xml是可以通过import标签进行导入的
applicationContext.xml
<?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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<import resource="beans.xml"/>
</beans>
测试
ApplicationContext context= new ClassPathXmlApplicationContext("applicationContext.xml");
UserT userT = context.getBean("userT2",UserT.class);
System.out.println(userT);
3、几种常见类型属性的注入
注入bean、数组array、List、map、set、props
beans.xml
<?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 id="address" class="com.spring.pojo.Address">
<property name="address" value="安徽省宿州市"/>
</bean>
<bean id="student" class="com.spring.pojo.Student">
<!--bean的注入-->
<property name="name" value="Sunzhong"/>
<property name="address" ref="address"/>
<!--数组的注入-->
<property name="books">
<array>
<value>西游记</value>
<value>红楼梦</value>
<value>三国演义</value>
<value>水浒传</value>
</array>
</property>
<!--List注入-->
<property name="hobbies">
<list>
<value>听歌</value>
<value>爬山</value>
<value>看电影</value>
</list>
</property>
<!--map注入-->
<property name="card">
<map>
<entry key="中国银行" value="12345645646124896423"/>
<entry key="身份证" value="12345645646124896423"/>
</map>
</property>
<property name="games">
<set>
<value>LOL</value>
<value>王者荣耀</value>
<value>QQ飞车</value>
</set>
</property>
<property name="info">
<props>
<prop key="学号">2202447</prop>
<prop key="性别">男</prop>
<prop key="年龄">24</prop>
</props>
</property>
</bean>
</beans>
pojo:Student.java
private String name;
private Address address;//Address.java
private String []books;
private List<String> hobbies;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
set....
get....
bean作用域:
用法:
<bean id="" class="" scope="singleton/prototype">
......
</bean>
区别:
- singleton 单实例,prototype 多实例
- 设置 scope 值是 singleton 时候,加载 spring 配置文件时候就会创建单实例对象
- 设置 scope 值是 prototype 时候,不是在加载 spring 配置文件时候创建 对象,在调用
getBean 方法时候创建多实例对象
bean管理(外部属性文件):
1、 导入jar包
<dependencies>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
</dependencies>
2、 编写外部属性文件
jdbc.properties
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/test
prop.userName=root
prop.password=sz@mysql
3、 把外部属性文件导入到spring配置中
* 引入 context 名称空间
<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: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">
<!--引入外部属性文件-->
<context:property-placeholder location="classpath: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>
二、基于注解方式
1、什么是注解
(1)注解是代码特殊标记,格式:@注解名称(属性名称=属性值, 属性名称=属性值…)
(2)使用注解,注解作用在类上面,方法上面,属性上面
(3)使用注解目的:简化 xml 配置
2、Spring 针对 Bean 管理中创建对象提供注解
(1)@Component
(2)@Service
(3)@Controller
(4)@Repository
- 上面四个注解功能是一样的,都可以用来创建 bean 实例(用来区分三层模型)
用法:
- 依赖:Spring-aop
- 开启扫描
<!--配置扫描-->
<context:component-scan base-package="com.spring"/>
- 开启注解
<!--开启注解-->
<context:annotation-config/>
- 示例-基于注解方式实现属性注入
(1)@Autowired:根据属性类型进行自动装配
第一步 把 service 和 dao 对象创建,在 service 和 dao 类添加创建对象注解
第二步 在 service 注入 dao 对象,在 service 类添加 dao 类型属性,在属性上面使用注解
@Service
public class UserService {
//定义 dao 类型属性
//不需要添加 set 方法
//添加注入属性注解
@Autowired
private UserDao userDao;
public void add() {
System.out.println("service add.......");
userDao.add();
}
}
(2)@Qualifier:根据名称进行注入
这个@Qualifier 注解的使用,和上面@Autowired 一起使用
//定义 dao 类型属性
//不需要添加 set 方法
//添加注入属性注解
@Autowired //根据类型进行注入
@Qualifier(value = "userDaoImpl1") //根据名称进行注入
private UserDao userDao;
(3)@Resource:可以根据类型注入,可以根据名称注入
//@Resource
//根据类型进行注入
@Resource(name = "userDaoImpl1") //根据名称进行注入
private UserDao userDao;
(4)@Value:注入普通类型属性
@Value(value = "abc")
private String name;
- 示例-完全注解开发(这里我没好好看~)
(1)创建配置类,替代 xml 配置文件
@Configuration //作为配置类,替代 xml 配置文件
@ComponentScan(basePackages = {"com.atguigu"})
public class SpringConfig {
}
(2)编写测试类
@Test
public void testService2() {
//加载配置类
ApplicationContext context= new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean("userService", UserService.class);
System.out.println(userService);
userService.add();
}