Java打怪之路----Spring框架之IOC

(一)Spring概述

Spirng 是一种轻量级开源的框架。
核心是IOC容器、AOP、JDBCTemplate和事务管理。
IOC:控制反转:把创建对象的过程交给Spring进行管理。
AOP:面向切面,不修改源代码进行功能增强

//Spring初体验
package com.sgyj.spring;

public class User {
    
    
    public void add(){
    
    
        System.out.println("add");
    }
}
package com.sgyj.spring;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.applet.Applet;
import java.applet.AppletContext;


public class TestAdd {
    
    
    @Test
    public void add(){
    
    
        ApplicationContext context= new ClassPathXmlApplicationContext("bean1.xml");
        User user=context.getBean("user",User.class);
        System.out.println(user);

    }
}


(二)IOC容器

2.1IOC容器的底层实现原理

高屋建瓴:IOC底层实现主要是结合以下三种方式实现

  1. XML解析
  2. 工厂模式
  3. 反射

Why:IOC容器的主要作用在于进行代码的解耦合
How:当我们使用Service类去调用Dao类时:
在这里插入图片描述
xml解析使用的时BeanFactory或者ApplicationContext

ApplicationContext context= new ClassPathXmlApplicationContext("bean1.xml");

2.2Spring提供给IOC容器的两种实现方式

2.2.1、BeanFactory

IOC容器的基本实现,加载配置文件时候不会创建对象,在调用了getBean()方法后才去创建对象。

2.2.2、ApplicationContext

BeanFactory接口的子接口,加载配置文件的时候就会把配置文件的对象进行创建。

(三)IOC操作Bean管理

3.1基于xml方式

Spring中的bean有几种类型?区别是什么
Spring中有两种bean,一种是普通bean,另一种是工厂bean(FactoryBean)
普通bean是指:在配置文件中定义的bean类型就是返回类型
工厂bean是指:在配置文件中定义的bean类型可以与返回类型不一样

--------普通Bean相关---------

3.1.1创建对象

需要在xml文件中使用 <bean></bean>创建对象

       <bean id="user" class="com.sgyj.spring.User"></bean>

3.1.2注入属性(依赖注入)

依赖注入的意思就是给对象设置相应的参数

3.1.2.1使用set方法进行注入

关键字 property

<?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">
<!--> 使用set方法给dept注入属性<!-->
    <bean id="dep" class="com.sgyj.bean.Dep">
        <property name="name" value="销售部"></property>
    </bean>
</beans>
package com.sgyj.bean;

import com.sgyj.Service.EmpService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Dep {
    
    
    private String name;

    public void setName(String name) {
    
    
        this.name = name;
    }

    @Test
    public void TestSet(){
    
    
        //这里的getbean的第一个参数值  要和xml文件中 给dep起的别名一致
        ApplicationContext context=new ClassPathXmlApplicationContext("bean3.xml");
        Dep dep=context.getBean("dep",Dep.class);
        System.out.println(dep.name);
    }
}

3.1.2.2使用有参构造器进行注入

关键字:constructor-arg

public class Orders {
    
    
 //属性
 private String oname;
 private String address;
 //有参数构造
 public Orders(String oname,String address) {
    
    
 this.oname = oname;
 this.address = address;
 } }
<!--3 有参数构造注入属性--> <bean id="orders" class="com.atguigu.spring5.Orders">
 <constructor-arg name="oname" value="电脑"></constructor-arg>
 <constructor-arg name="address" value="China"></constructor-arg>
</bean>

3.1.2.3使用P名称空间注入

关键字: xmlns:p=“http://www.springframework.org/schema/p”

<bean id="book" class="com.atguigu.spring5.Book" p:bname="九阳神功" 
p:bauthor="无名氏"></bean>

3.1.3注入其他属性

上面是我们正常创建对象时,注入正常的属性,下面演示如何注入其他属性

3.1.3.1注入字面量(空值和特殊符号)

<property name="address">
 <null/>
</property>

3.1.3.2注入外部bean

实现:
(1)创建两个类service类和dao类
(2)在service调用dao里的方法
(3)在spring配置 文件中进行配置
配置
步骤一:在xml中分别配置servive与dao类对象的创建
步骤二:在service中注入dao对象,采用ref属性

public class UserService {
    
    
 //创建 UserDao 类型属性,生成 set 方法
 private UserDao userDao;
 public void setUserDao(UserDao userDao) {
    
    
 	this.userDao = userDao;
 }
 public void add() {
    
    
 	System.out.println("service add...............");
 	userDao.update();
 } }
 
<!--1 service 和 dao 对象创建--> 
<bean id="userService" class="com.atguigu.spring5.service.UserService">
 <!--注入 userDao 对象 name 属性:类里面属性名称 ref 属性:创建 userDao 对象 bean 标签 id 值 -->
 <property name="userDao" ref="userDaoImpl"></property>
</bean> 
<bean id="userDaoImpl" class="com.atguigu.spring5.dao.UserDaoImpl"></bean>

3.1.3.3注入内部bean

(1)一对多关系:部门和员工 一个部门有多个员工,一个员工属于一个部门
部门是一,员工是多
(2)在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示
注入内部bean的意思就是在员工类中有部门类的实例,需要对员工类中的部门类进行注入属性

<bean id="emp" class="com.atguigu.spring5.bean.Emp">
 <!--设置两个普通属性-->
 <property name="ename" value="lucy"></property>
 <property name="gender" value=""></property>
 <!--设置对象类型属性-->
 <property name="dept">
 <bean id="dept" class="com.atguigu.spring5.bean.Dept">
 <property name="dname" value="安保部"></property>
 </bean>
 </property>
</bean>

3.1.3.4注入级联赋值

与注入内部bean意思差不多,这里采用注入外部类的方式实现

<bean id="emp" class="com.atguigu.spring5.bean.Emp">
 <!--设置两个普通属性-->
 <property name="ename" value="lucy"></property>
 <property name="gender" value=""></property>
 <!--级联赋值-->
 <property name="dept" ref="dept"></property>
</bean> <bean id="dept" class="com.atguigu.spring5.bean.Dept">
 <property name="dname" value="财务部"></property>
</bean>

3.1.3.5注入数组、集合、Map类型属性

属性注入的代码

<bean id="stu" class="com.atguigu.spring5.collectiontype.Stu">
 <!--数组类型属性注入-->
 <property name="courses">
 <array>
 <value>java 课程</value>
 <value>数据库课程</value>
 </array>
 </property>
 <!--list 类型属性注入-->
 <property name="list">
 <list>
 <value>张三</value>
 <value>小三</value>
 </list>
 </property>
 <!--map 类型属性注入-->
 <property name="maps">
 <map>
 <entry key="JAVA" value="java"></entry>
 <entry key="PHP" value="php"></entry>
 </map>
 </property>
 <!--set 类型属性注入-->
 <property name="sets">
 <set>
 <value>MySQL</value>
 <value>Redis</value>
 </set>
 </property>
</bean>

将集合注入提取出来
(1)在 spring 配置文件中引入名称空间 util

<?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:p="http://www.springframework.org/schema/p"
 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 集合注入提取

<!--1 提取 list 集合类型属性注入--> <util:list id="bookList">
 <value>易筋经</value>
 <value>九阴真经</value>
 <value>九阳神功</value>
</util:list>
<!--2 提取 list 集合类型属性注入使用--> <bean id="book" class="com.atguigu.spring5.collectiontype.Book">
 <property name="list" ref="bookList"></property>
</bean>

--------工厂Bean相关---------

3.1.4工厂bean创建

第一步:创建类,让这个类实现FactoryBean接口
第二部:实现接口里的方法,在实现的方法中定义返回的类型

1、创建类

public class MyBean implements FactoryBean<Course> {
    
    
 //定义返回 bean
 	@Override
 	public Course getObject() throws Exception {
    
    
 	Course course = new Course();
 	course.setCname("abc");
 	return course;
 	}
 	@Override
	 public Class<?> getObjectType() {
    
    
 	return null;
 	}
 	@Override
 	public boolean isSingleton() {
    
    
 	return false;
 } 
 }

2、配置xml文件

<bean id="myBean" class="com.atguigu.spring5.factorybean.MyBean"></bean>

3、测试

@Test
public void test3() {
    
    
 ApplicationContext context =
 new ClassPathXmlApplicationContext("bean3.xml");
 Course course = context.getBean("myBean", Course.class);
 System.out.println(course);
}

注意:
1、如果是想要获取普通bean。配置文件中写的是MyBean,最终测试获取的对象就是mybean对象。而这里使用的是工厂Bean,所以获取到的返回值类型是Course 。
2、重写的getObject()的返回值类型设置为需要返回的类型,这里是想要 Course,所以返回值类型写Course
3、测试中,getBean中需要获取的是Course.class,写为Mybean.class会报错。

3.1.5Bean的作用域

1、什么是作用域:Bean的作用域是指我们设置的Bean实例是单实例还是多实例
2、如何设置单实例和多实例:

  1. 默认情况下是单实例
  2. 在 spring 配置文件 bean 标签里面有属性(scope)用于设置单实例还是多实例
  3. scope 属性值
  4. 第一个值 默认值,singleton,表示是单实例对象
  5. 第二个值 prototype,表示是多实例对象

3、单实例和多实例有什么区别
第一 singleton 单实例,prototype 多实例
第二 设置 scope 值是 singleton 时候,加载 spring 配置文件时候就会创建单实例对象
设置 scope 值是 prototype 时候,不是在加载 spring 配置文件时候创建 对象,在调用
getBean 方法时候创建多实例对象

3.1.6Bean的生命周期

1、通过调用无参构造函数创建bean对象
2、对Bean对象进行属性注入,调用set方法进行注入
3把bean实例传递给bean后置处理器的方法
4、执行bean的初始化方法
5、把bean的实例传递给bean后置处理器的方法
6、获取创建bean实例对象
7、执行销毁的方法

3.1.7Bean的自动装配

什么是自动装配:根据指定装配规则(属性名称或者属性类型),Spring 自动将匹配的属性值进行注入

<!--实现自动装配
 bean 标签属性 autowire,配置自动装配
 autowire 属性常用两个值:
 byName 根据属性名称注入 ,注入值 bean 的 id 值和类属性名称一样
 byType 根据属性类型注入
--><bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byName">
 <!--<property name="dept" ref="dept"></property>-->
</bean> <bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean> (2)根据属性类型自动注入
<!--实现自动装配
 bean 标签属性 autowire,配置自动装配
 autowire 属性常用两个值:
 byName 根据属性名称注入 ,注入值 bean 的 id 值和类属性名称一样
 byType 根据属性类型注入
--><bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byType">
 <!--<property name="dept" ref="dept"></property>-->
</bean> <bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean>

3.1.8Bean引入外部属性文件

把外部 properties 属性文件引入到 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"> ⚫ 在 spring 配置文件使用标签引入外部属性文件
<!--引入外部属性文件--> <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>

3.2基于注解方式

3.2.1Spring提供的注解

(1)@Component
(2)@Service
(3)@Controller
(4)@Repository
四个注解都可以来实现Bean对象的创建

3.2.2基于注解方式实现对象创建(新概念:组件扫描)

之前对象的创建是通过xml文件中进行创建,现在只需要对需要创建的bean上面添加四个注解

@Service
public class UserService {
    
    
	    public void add(){
    
    
        System.out.println("+++");
}

public class demo1 {
    
    
    @Test
    public void test(){
    
    
        ApplicationContext context=new ClassPathXmlApplicationContext("bean4.xml");
        UserService userService=context.getBean("userService",UserService.class);
        userService.add();
    }
}

3.2.3基于注解方式实现属性注入

(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;

3.2.4全注解开发

不使用xml文件,创建配置类来替换xml配置文件。

@Configuration //作为配置类,替代 xml 配置文件
@ComponentScan(basePackages = {
    
    "com.atguigu"})
public class SpringConfig {
    
    
}

猜你喜欢

转载自blog.csdn.net/weixin_44020747/article/details/121302626