SPRING
控制反转(IOC),面向切面编程(AOP)
组成
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZAPMsvkb-1636435587289)(Spring.assets/20170227200701831.gif)]
1、IOC理论推导
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ii94aYbB-1636435587293)(Spring.assets/1634883397649.png)]
在之前的业务中,用户需求可能会影响我们原来的代码,我们需要根据用户需求去修改源码!如果程序代码量十分大,修改一次的成本代价十分昂贵
我们使用一个set接口实现
public class UserServiceImpl implements UserService{
private UserDao userDao;
//利用set进行动态实现值的注入!
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void getUser() {
userDao.getUser();
}
}
- 之前,程序是主动创建对象!控制权在程序员手上
- 使用了set注入后,程序不在具有主动性,而是变成了被动的接受对象!
- 这种思想,从本质上解决了问题,我们程序员不用再去管理对象的创建了,系统的耦合性大大降低,可以更加专注的在业务的实现上!这是IOC的原型!
2、IOC本质
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
上面的改法
在resources中创建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就是java对象 , 由Spring创建和管理-->
<bean id="ud" class="com.leitao.dao.UserDaoImpl"/>
<bean id="udmi" class="com.leitao.dao.UserMysqlImpl"/>
<bean id="udoi" class="com.leitao.dao.UserDaoOracleImpl"/>
<bean id="usi" class="com.leitao.service.UserServiceImpl">
<property name="userDao" ref="ud"/>
</bean>
</beans>
改的话直接改 ref 引用就行了
测试类MyTest
public class MyTest {
public static void main(String[] args) {
//用户调用的是业务层,dao层他们不需要接触!
/*UserService userService = new UserServiceImpl();
((UserServiceImpl)userService).setUserDao(new UserMysqlImpl());
userService.getUser();*/
//获取ApplicationContext;拿到spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserServiceImpl usi = (UserServiceImpl) context.getBean("usi");
usi.getUser();
}
}
2、无参构造创建对象,默认
pojo里面User
public class User {
private String name;
public User() {
System.out.println("User的无参构造");
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("show.......");
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
beans.xml
<bean id="user" class="com.leitao.pojo.User">
<property name="name" value="张三"/>
</bean>
MyTest
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
user.show();
System.out.println(user);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0KcKPCIb-1636435587294)(Spring.assets/1634897960574.png)]
3、有参构造创建对象
-
下标赋值
User里面创建有参构造方法
beans.xml
<!--第一种--> <bean id="user" class="com.leitao.pojo.User"> <constructor-arg index="0" value="雷涛学java"/> </bean>
-
通过参数类型创建,如果参数有两个String就有问题(不推荐使用)
<!--第二种--> <bean id="user" class="com.leitao.pojo.User"> <constructor-arg type="java.lang.String" value="leitao"/> </bean>
-
直接通过参数名(推荐)
<!--第三种--> <bean id="user" class="com.leitao.pojo.User"> <constructor-arg name="name" value="发射点发给大家喝咖啡的"/> </bean>
**总结:**在配置文件加载的时候,容器中管理的对象就已经初始化了!
4、spring配置
- 别名
<!--别名,如果添加了别名,我们也可以使用别名获取到这个对象-->
<alias name="user" alias="bieming"/>
- Bean配置
<!--name也是别名,可以取多个别名-->
<bean id="usert" class="com.leitao.pojo.UserT" name="t,u2,u3,u4">
<property name="name" value="分公司看到了法国"/>
</bean>
- import
这个import,一般用于团队开发使用,它可以将多个配置文件,导入合并为一个
applicationContext.xml
<import resource="beans.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>
到时候直接使用总配置文件
5、DI依赖注入
-
构造器注入
前面说过了
-
set方式注入【重点】
- 依赖注入:Set注入
- 依赖:Bean对象的创建依赖于容器
- 注入:Bean对象
- 依赖注入:Set注入
-
拓展方式注入
1、spring 快速入门步骤
1、导入spring开发的基本包坐标
<!--导入坐标-->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.10</version>
</dependency>
</dependencies>
2、编写Dao接口和实现类
UserDao
public interface UserDao {
public void save();
}
UserDaoImpl
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("save running");
}
}
3、创建spring核心配置文件
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 http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
4、在spring配置文件中配置UserDaoImpl
<bean id="userDao" class="com.leitao.dao.impl.UserDaoImpl"></bean>
5、使用spring的API获得Bean实例
public class UserDaoDemo {
public static void main(String[] args) {
ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) app.getBean("userDao");
userDao.save();
}
}
2、spring配置文件
2.1Bean标签基本配置
用于配置对象交由spring来创建
默认情况下它调用的是类中的无参构造函数,如果没有则创建不成功
基本属性:
- id:Bean实例在spring容器中的唯一标识
- class:Bean的全限定名称
2.2Bean标签范围配置
scope:值对象的作用范围
- singleton:默认值,单例的
- Bean实例化个数:1个
- Bean的实例化时机:当spring核心文件被加载时,实例化配置的Bean实例
- Bean的生命周期:
- 对象创建:当应用加载,创建容器时,对象就被创建了
- 对象运行:只要容器在,对象一直活着
- 对象销毁:当应用卸载,销毁容器,对象就被销毁
applicationContext.xml
<bean id="userDao" class="com.leitao.dao.impl.UserDaoImpl" scope="singleton"></bean>
UserDaoDemo
ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) app.getBean("userDao");
UserDao userDao2 = (UserDao) app.getBean("userDao");
System.out.println(userDao);
System.out.println(userDao2);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-daoqhghA-1636435587296)(Spring.assets/1634724076751.png)]
- Prototype:多例的
- Bean实例化个数:多个
- Bean的实例化时机:当调用getBean()方法时,实例化配置的Bean实例
- Bean的生命周期:
- 对象创建:当使用对象时,创建新的对象实例
- 对象运行:只要对象在使用中,就一直活着
- 对象销毁:当对象长时间不用时,被java的垃圾回收机制回收
<bean id="userDao" class="com.leitao.dao.impl.UserDaoImpl" scope="prototype"></bean>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k3VXLX61-1636435587298)(Spring.assets/1634724131852.png)]
- request
- session
- global session
2.3Bean生命周期配置
- init-method:指定类中的初始化方法名称
- destroy-method:指定类中的销毁方法名称
applicationContext.xml
<bean id="userDao" class="com.leitao.dao.impl.UserDaoImpl" init-method="init" destroy-method="destroy"></bean>
UserDaoDemo
public class UserDaoDemo {
public static void main(String[] args) {
ClassPathXmlApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) app.getBean("userDao");
System.out.println(userDao);
app.close();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hOWEnjx6-1636435587300)(Spring.assets/1634726017646.png)]
2.4Bean实例化三种方式
- 无参构造方法实例化
- 工厂静态方法实例化
创建factory包里面StaticFatory
public class StaticFatory {
public static UserDao getUserDao(){
return new UserDaoImpl();
}
}
applicationContext.xml
<bean id="userDao" class="com.leitao.factory.StaticFatory" factory-method="getUserDao"></bean>
执行UserDaoDemo
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y4yMvMkk-1636435587301)(Spring.assets/1634727894237.png)]
- 工厂实例方法实例化
创建factory包里面DynamicFatory
public class DynamicFatory {
public UserDao getUserDao(){
return new UserDaoImpl();
}
}
applicationContext.xml
<bean id="fatory" class="com.leitao.factory.DynamicFatory"></bean>
<bean id="userDao" factory-bean="fatory" factory-method="getUserDao"></bean>
执行UserDaoDemo
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-moLTFf54-1636435587302)(Spring.assets/1634728674761.png)]
2.5Bean的依赖注入方式
-
set方法注入
-
(引用数据类型)
UserServiceImpl
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void save() {
userDao.save();
}
}
applicationContext.xml
<bean id="userDao" class="com.leitao.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.leitao.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
或
p命名空间注入
<bean id="userDao" class="com.leitao.dao.impl.UserDaoImpl"></bean>
xmlns:p="http://www.springframework.org/schema/p"
<bean id="userService" class="com.leitao.service.impl.UserServiceImpl" p:userDao-ref="userDao"></bean>
userController
public class UserController {
public static void main(String[] args) {
ApplicationContext app =new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) app.getBean("userService");
userService.save();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u3bfdGFb-1636435587303)(Spring.assets/1634781732339.png)]
- 有参构造方式注入
UserServiceImpl
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
public UserServiceImpl() {
}
public void save() {
userDao.save();
}
}
applicationContext.xml
<bean id="userDao" class="com.leitao.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.leitao.service.impl.UserServiceImpl">
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
UserController和结果同上
2.6Bean的依赖注入的数据类型
-
普通数据类型
- set方式
userDaoImpl
private String username; private int age; public void setUsername(String username) { this.username = username; } public void setAge(int age) { this.age = age; } public void save() { System.out.println(username+"+++++"+age); System.out.println("save running"); }
applicationCpntext.xml
<bean id="userDao" class="com.leitao.dao.impl.UserDaoImpl"> <property name="username" value="张三"></property> <property name="age" value="18"></property> </bean> <bean id="userService" class="com.leitao.service.impl.UserServiceImpl"> <constructor-arg name="userDao" ref="userDao"></constructor-arg> </bean>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QCtcDmpK-1636435587304)(Spring.assets/1634793706178.png)]
-
引用数据类型
-
集合数据类型
创建一个domain包里面User类
userImpl
private List<String> strList;
private Map<String, User> userMap;
private Properties properties;
public void setStrList(List<String> strList) {
this.strList = strList;
}
public void setUserMap(Map<String, User> userMap) {
this.userMap = userMap;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
System.out.println(strList);
System.out.println(userMap);
System.out.println(properties);
applicationContext.xml
<bean id="userDao" class="com.leitao.dao.impl.UserDaoImpl">
<property name="strList">
<list>
<value>fdgfdg</value>
<value>fdgs</value>
<value>hfggfh</value>
<value>gfhtydjryt</value>
</list>
</property>
<property name="userMap">
<map>
<entry key="U1" value-ref="user1"></entry>
<entry key="U2" value-ref="user2"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="p1">pppp1</prop>
<prop key="p2">pppp2</prop>
<prop key="p3">pppp3</prop>
</props>
</property>
</bean>
<bean id="user1" class="com.leitao.domain.User">
<property name="name" value="李四"></property>
<property name="addr" value="迁安"></property>
</bean>
<bean id="user2" class="com.leitao.domain.User">
<property name="name" value="路西"></property>
<property name="addr" value="天津"></property>
</bean>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ww52eBbL-1636435587305)(Spring.assets/1634872142761.png)]