IOC理论推导
对IOC的简单理解
现在用户有需求了,想用一个叫做Mysql的UserDao接口实现类我们怎么做??
public class UserDaoMysqlImpl implements UserDao{
@Override
public void getUser() {
System.out.println("获取mysql的相关数据");
}
}
很简单呀, 实现接口重写方法,即可。在Service层中再将UserDao接口的实现类改为Mysql即可
UserDao userDao=new UserDaoMysqlImpl();
- 这样看起来说的过去,用户每想要一个需求告诉程序员即可,程序员来改,但是这样来好像有点问题,什么事情都得告诉程序员来做,那他们不得累死呀。。。
所以爱偷懒的程序员们想了一个好办法,做一个set注入,用户想用什么就告诉set,不用直接告诉我了
演变
private UserDao userDao;
//这里接收的参数应该是一个实现类对象
public void setUserDao( UserDao userDao){
this.userDao=userDao;
}
比如说现在用户又想用Oracl了,我们已经建立好了实现类。那么用户就可以自取自用了
UserService service=new UserServiceImpl();
((UserServiceImpl) service).setUserDao(new UserDaoOraclImpl());
service.getUser();
思考 ?
大家想一下如果用户就相当于是测试类的话现在的控制权力交在类谁的手上。用户自己
- 这大概就是控制反转的核心了吧
spring的搭建
- 在maven中添加依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.12</version>
</dependency>
- 在resource中建立主配置文件,下面是Spring的文档官网
https://docs.spring.io/spring-framework/docs/6.0.0-SNAPSHOT/reference/html/core.html#beans-introduction
主配置文件位置
这里我直接给大家 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//类型强转
UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl");
//所以说现在只需要进行修改配置即可
userServiceImpl.getUser();
输出结果 —> 获取oracl的相关数据
但是当我们想使用有参构造器的时候怎么半啊
- 不用担心Spring有解决办法
注入依赖
一: 构造器注入 在上面
二:set注入
public class Student {
private String name;
//引用
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> game;
private String wife;
private Properties info;
//各种set get方法 以及重写toString方法
public class Address {
private String address;
//用来做引用类型的注入
- bean中的注入
<bean id="address" class="org.example.Address">
<property name="address" value="山东潍坊"/>
</bean>
<bean id="student" class="org.example.Student">
<!-- 第一种普通数值注入-->
<property name="name" value="家森"/>
<!-- 第二种ref引用注入-->
<property name="address" ref="address"/>
<!-- 第三种数组注入-->
<property name="books">
<array>
<value>红楼梦</value>
<value>三国演义</value>
<value>水浒传</value>
</array>
</property>
<!-- 第四种list注入-->
<property name="hobbys">
<list>
<value>风花雪月</value>
<value>听歌赏舞</value>
<value>苦逼代码</value>
</list>
</property>
<!-- 第五种Map集合-->
<property name="card">
<map>
<entry key="身份证" value="121212122222222121"/>
<entry key="银行卡" value="123423423123412djf"/>
</map>
</property>
<!-- Set集合-->
<property name="game">
<set>
<value>LOL</value>
<value>BoB</value>
<value>COC</value>
</set>
</property>
<!-- 空值null-->
<property name="wife">
<null/>
</property>
<!-- Properties配置文件-->
<property name="info">
<props>
<prop key="driver">12345</prop>
<prop key="url">qwerooo</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
扩展方式注入
p命名空间
案例我就不写了为大家解读解读文档吧。
可以理解为对属性的另一种扩展的注入方式
使用前提:在xml文中导入 xmlns:p=“http://www.springframework.org/schema/p”
c命名空间
同样也需要在xml文件中导入 xmlns:c=“http://www.springframework.org/schema/c”
Bean的作用域
单例模式演示
官方解释
- 个人理解于翻译
大致意思就是说你如果定义了Bean的作用域为单例(singleton)那么在Spring容器中有且只有一个实例化对象
原型模式
每次从容器中取出一个对象都是不同的
Bean的自动装配
- ByName保证bean的id唯一,并且这个bean需要和自动注入的属性的set方法一致
- ByType保证bean的class唯一,并且这个bean需要和自动注入的属性类型一致**
现在有三个类
public class Cat {
public void shot(){
System.out.println("喵喵");
}
}
public class Dog {
public void shout(){
System.out.println("汪汪");
}
}
public class People {
private String name;
private Cat cat;
private Dog dog;
//各种get/set方法
现在我们使用自动装配的方法 将Cat 和dog的引用注入进去
- ByType
type顾名思义是通过类型来寻找的即使没有id也是可以的
注解实现自动装配
- 使用注解的前提
配置注解的支持
<?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: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 自动装配 通过ByType实现而且要求对象存在
@Qualifier可以指定选择的对象,复杂情况中使用
*还有一种比较老的注解@Resource 默认是ByName方式实现,没有找到id就会通过ByType方式进行寻找
注解开发
首先要在xml的bean标签中添加上
<!-- 指定要扫描的包 ,这个包下的注解就会生效-->
<context:component-scan base-package="org.example"/>
@Component
public class People {
相当于
<bean id="people" class="org.example.People"/>
@Value("家森")
private String name;
<property name="name" value="家森"/>
其中还有 @Scope(“prototype”)相当于作用域
分析xml和注解
1.xml是万能的使用于任何场所,维护简单方便
2.注解不是自己的类使用不了,维护起来相对复杂
3.xml用来管理bean
4.注解只负责完成属性的注入
使用Javaconfig实现配置
使用javaconfig获取对象的方式
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}