Spring IOC学习

原理

什么是IOC(控制反转)

1、就是把对象的创建和对象之间的调用过程,交给Spring管理
2、使用目的:为了降低耦合度

IOC底层原理

a、xml解析、反射
在这里插入图片描述

b、工厂模式
通过工厂模式来降低耦合度
在这里插入图片描述

IOC(接口)

1、IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
2、Spring提供IOC容器实现两种方式:(两个接口)
(1)BeanFactory:IOC容器基本实现,是Spring内部的使用接口。
*加载配置文件时不会创建对象,获取(使用)对象时才去创建对象。
(2)ApplicationContext: BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员使用
*加载配置文件时就会把配置文件对象进行创建

ApplicationContext接口的实现类

在这里插入图片描述FileSystem…:需要绝对路径(带盘符)
ClassPath…:src下路径

具体操作

IOC操作Bean管理

1、什么是Bean管理

		a、Spring创建对象
		b、Spring注入属性

2、Bean管理操作两种方式

		1、基于xml配置文件方式实现
		2、基于注解方式实现
基于xml配置文件方式实现
a、**基于xml方式创建对象**
	 (1)在spring配置文件中,使用bean标签,标签中添加对应属性,就可以实现对象的创建
	    <bean id="user" class="com.company.User"></bean>
	 (2) 常用属性:
	    		*id属性   :唯一标识
	    		*class属性:类全路径(包类路径) 
	    		*name属性(一般不用):id属性中不能加特殊符号,name可以
	 (3)创建对象时,默认执行无参构造方法
b、**基于xml方式注入属性**
	 (1)依赖注入,即注入属性
	 **第一种注入方式:即set方式注入**
	 	第一步:
package com.company;
public class Book {

    //定义属性
    private String bName;
    private String bauthor;

    //创建属性对应的set方法
    public void setbName(String bName) {
        this.bName = bName;
    }
}
第二步
<!--    set方法注入属性-->
    <bean id="book" class="com.company.Book">
<!--        使用property完成属性注入
            name:类里边属性名称
            value:向属性注入的值-->
        <property name="bName" value="百科全书"></property>
        <property name="bauthor" value="常子东"></property>
    </bean>

	 **第二种注入方式:有参方式注入**
	 第一步:
	 package com.company;
	public class Orders {
    private String  oName;
    private String  address;

    //有参构造
    public Orders(String oName, String address) {
        this.oName = oName;
        this.address = address;
    }
}
	第二步:
	<!--    有参构造注入属性-->
    <bean id="orders" class="com.company.Orders">
        <constructor-arg name="oName" value="主机"></constructor-arg>
        <constructor-arg name="address" value="城"></constructor-arg>
    </bean>
    
c、p名称空间注入(了解)
	(1)

xml注入其他类型属性

1、null
<property name="address">
            <null></null>
        </property>
2、特殊符号(值:<<南京>>)
	<property name="bauthor">
            <value>
                <![CDATA[<<南京>>]]>
            </value>
        </property>
注入属性

外部bean

(1)创建两个类:service类和dao类
(2)在service调用dao里面的方法
(3)Spring配置文件中进行配置

<bean id="userService" class="com.company.service.UserService">
<property name="userDao" ref="userDaoImpl"></property> 
</bean>
<bean id="userDaoImpl"     class="com.company.dao.UserDaoImpl"></bean>

内部bean

一对多关系:部门与员工

package com.company.bean;

//员工类
public class Emp {
    private String eName;
    private String gender;
//    员工属于某一部门,用对象形式表示
    private Dept dept;
    public void seteName(String eName) {
        this.eName = eName;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public void  add(){
        System.out.println(eName+":"+gender+":"+dept);
    }
}
<bean id="emp" class="com.company.bean.Emp">
        <property name="eName" value="chang"></property>
        <property name="gender" value="男"></property>

        <property name="dept">
            <bean id="dept" class="com.company.bean.Dept">
                <property name="dName" value="保卫处"></property>
            </bean>
        </property>
        
    </bean>

级联赋值

<!--    级联赋值-->
        <bean id="emp" class="com.company.bean.Emp">
            <property name="eName" value="chang"></property>
            <property name="gender" value="男"></property>

            <property name="dept" ref="dept"></property>
        </bean>

        <bean id="dept" class="com.company.bean.Dept">
            <property name="dName" value="财务部"></property>  
        </bean>

xml注入集合属性
1、注入数组类型属性
2、注入List集合类型属性
3、注入Map集合类型属性

(1)创建类,定义数组、list等类型属性,生成对应的set方法
(2)在Spring配置文件中进行配置
package com.spring.collection;
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> maps;

    //set集合类型
    private Set<String> sets;

    public void setCourses(String[] courses) {
        this.courses = courses;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setMaps(Map<String, String> maps) {
        this.maps = maps;
    }

    public void setSets(Set<String> sets) {
        this.sets = sets;
    }

    public void test(){
        System.out.println(Arrays.toString(courses));
        System.out.println(list);
        System.out.println(maps);
        System.out.println(sets);
    }
}
    <bean id="stu" class="com.spring.collection.Stu">
<!--        数组类型-->
        <property name="courses">
            <array>
                <value>java课程</value>
                <value>DB课程</value>
            </array>
        </property>

<!--        List类型-->
        <property name="list">
            <list>
                <value>张三</value>
                <value>小张</value>
            </list>
        </property>

        <!--        List类型-->
        <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>

在集合中设置对象类型值

    <bean id="stu" class="com.spring.collection.Stu">
<!--        注入list集合类型,值为对象-->
        <property name="courseList">
            <list>
                <ref bean="course1" ></ref>
                <ref bean="course2" ></ref>
            </list>
        </property>
    </bean>

    <bean id="course1" class="com.spring.collection.Course">
        <property name="cName" value="Spring框架"></property>
    </bean>
    
    <bean id="course2" class="com.spring.collection.Course">
        <property name="cName" value="MyBatis框架"></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: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-beans.xsd">

</beans>

(2)使用util标签完成list集合注入提取

<!--    提取list集合类型属性注入-->
    <util:list id = "book.list">
        <value>易筋经</value>
        <value>九阴真经</value>
        <value>九阳神功</value>
    </util:list>

<!--    提取list集合类型属性注入  使用-->
    <bean id="book" class="com.spring.collection.Book">
        <property name="list" ref="book.list">
        </property>
    </bean>
IOC操作Bean管理
spring有两种类型的bean:一种是普通bean,另一种是工厂bean(FactoryBean)
(1)普通bean:上面例子(在配置文件中定义什么类型,返回什么类型)
(2)FactoryBean:(在配置文件中定义bean类型可以和返回类型不一样)

工厂Bean:
(1)创建类,让这个类作为工厂bean(实现接口FactoryBean)
(2)实现接口中的方法,在实现的方法中定义返回的bean类型

public class MyBean implements FactoryBean<Course> {


//    定义返回的bean对象类型
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setcName("abc");
        return course;
    }
}

IOC操作Bean管理(bean作用域:单实例还是多实例,默认单实例)

//默认单实例

    @Test
    public void testCollection02(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("appliction2.xml");

        Book book1 = context.getBean("book", Book.class);
        Book book2 = context.getBean("book", Book.class);
//        book.test();
        System.out.println(book1);
        System.out.println(book2);
        System.out.println(book1.equals(book2));
    }

(1)在Spring配置文件中bean标签中有属性(scope)用于设置单还是多实例
(2)scope属性值

1、singleton:表示单实例对象(默认)
		设置为此值时,加载spring配置文件时就回创建单实例对象
2、prototype,表示多实例对象
		设置为此值时,调用getBean方法时创建多实例对象

<bean id="book" class="com.spring.collection.Book" scope="prototype">
        
    </bean>
 3、request:创建对象放到request中(不常用)
4、session:创建对象放到session中(不常用)

bean生命周期(面试重点):从对象创建到对象销毁的过程

a、通过构造器创建bean实例(无参构造)
b、为bean的属性设置值和队其他bean引用(set方法)
	把bean实例传递给bean后置处理器的方法(postProcessBeforeInitialization方法)
c、调用bean的初始化方法(要进行配置)
	把bean实例传递给bean后置处理器的方法(postProcessAfterInitialization方法)
d、bean可以使用(获取到对象)
e、容器关闭,调用bean的销毁方法(需要进行配置销毁方法)
     <bean id="orders" class="com.spring.bean.Orders" init-method="initMethod" destroy-method="destoryMethod">
        <property name="oName" value="手机"></property>
    </bean>

<!--    配置后置处理器,配置后为所有bean添加后置处理器-->
    <bean id="myBeanPost" class="com.spring.bean.MyBeanPost"></bean>
package com.spring.bean;

public class Orders {

    //无参数构造
    public Orders() {
        System.out.println("第一步 执行无参数构造创建bean实例");
    }

    public String oName;

    public void setoName(String nName) {
        this.oName = nName;
        System.out.println("第二步  调用set方法设置属性值");
    }

    //创建执行的初始化方法
    public void initMethod(){
        //配置文件中的    <bean id="orders" class="com.spring.bean.Orders" init-method="initMethod">
        System.out.println("第三步 执行初始化方法");
    }

    public void destoryMethod(){
        System.out.println("第五步 执行销毁的方法");
    }
}
//后置处理器类
public class MyBeanPost implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之前执行的方法");
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之后执行的方法");
        return null;
    }
}

    @Test
    public void testCollection04(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("appliction4.xml");

//        ClassPathXmlApplicationContext context =
//                new ClassPathXmlApplicationContext("appliction4.xml");

        Orders orders = context.getBean("orders",Orders.class);
        System.out.println("第四步,获取创建bean实例对象");
        System.out.println(orders);

//        手动销毁bean实例
        ((ClassPathXmlApplicationContext) context).close();
    }

XML方式的自动装配(一般使用注解实现自动装配
自动装配:根据指定的装配规则,Spring自动将匹配的属性值进行注入(上面全部是手动装配)
两种方式:根据属性名称、根据属性类型

<!--    自动装配
        bean标签属性autowire,配置自动装配
        autowire有两个值:
                byName根据属性名称注入 :注入bean的id值和类属性名称一样
                byType根据属性类型注入 :
-->
    <bean id="emp" class="com.spring.autowire.Emp" autowire="byType"></bean>
    <bean id="dept" class="com.spring.autowire.Dept"></bean>

XML方式引入外部属性文件

(1)直接配置数据库信息
配置德鲁伊连接池
引入德鲁伊jar包

   <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="jdbc:mysql:///localhost:3306/userDb" />
        <property name="username" value="root" />
        <property name="password" value="123456" />
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    </bean>

(2)通过外部属性文件配置数据库连接池
创建外部属性文件,properties格式文件,写数据库信息

prop.driverClass = com.mysql.jdbc.Driver
prop.url = jdbc:mysql:///localhost:3306/userDb
prop.userName = root
prop.password = 123456

把外部properties属性文件引入spring配置文件中
a、引入context命名空间
b、spring配置文件中使用标签引入

<?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: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="url" value="${prop.url}" />
        <property name="username" value="${prop.userName}" />
        <property name="password" value="${prop.password}" />
        <property name="driverClassName" value="${prop.driverClass}" />
    </bean>
</beans>
基于注解方式实现

1、什么是注解:
(1)注解是代码特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值…)
(2)使用注解,可以作用在类上、方法上、属性上
(3)使用注解的目的:简化XML配置
2、Spring针对Bean管理中创建对象提供的注解

@Component    @Service	   @Controller     @Repository
四个注解功能相同,都可以用来创建对象

第一步 引入依赖
在这里插入图片描述
第二步 开启组件扫描

<?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: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">

<!--    开启组件扫描
1、扫描多个包,多个包之间用逗号隔开
2、扫描包的上层目录
-->
<!--    写法1-->
    <context:component-scan base-package="com.spring.dao,com.spring.Service"></context:component-scan>
<!--写法2-->
    <context:component-scan base-package="com.spring"></context:component-scan>

<!--    手动配置过滤器
        use-default-filters="false"表示不使用现在默认的filter,自己配置filter
        context:include-filter  设置扫描哪些内容
-->
    <context:component-scan base-package="com.spring" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>   
         <!--只扫描带Controller注解的-->
    </context:component-scan>

<!--    扫描包中的全部内容-->
<!--    context:exclude-filter  设置哪些内容不进行扫描-->
    <context:component-scan base-package="com.spring" use-default-filters="false">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>  
        	   <!--不扫描带Controller注解的-->
    </context:component-scan>
    
</beans>

第三步 创建类,在类上面添加创建对象注解

package com.spring.Service;
import org.springframework.stereotype.Component;
//加上注解就不需要在配置文件中配置
//注解后的value值可以省略     默认值是类名称,首字母小写
@Component
public class UserService {
    public void add(){
        System.out.println("Service add.....");
    }
}

基于注解方式属性注入

@AutoWired :根据属性类型进行自动装配

//第一步创建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();
    }
}

@Qualifier :根据属性名称进行注入

@Repository(value = "userDaoImpl11")
public class UserDaoImpl implements UserDao{
//这个注解要和@AutoWired一起使用
@Service
public class UserService {
    /*
    * 定义dao类型属性
    * 不需要添加set方法
    * 添加注入属性注解*/
    @Autowired
    //一个借口有多个实现类,指定实现类的名称注入
    @Qualifier(value = "userDaoImpl11")
    private UserDao userDao;

    public void add(){
        System.out.println("Service add.....");
        userDao.add();
    }
}

@Resource (不是spring提供 不推荐):可以根据类型注入,也可以根据名称注入

@Service
public class UserService{

    @Resource  //根据类型进行注入
//      @Resource(name = "userDaoImpl11")  //根据名称进行注入
    private UserDao userDao;
    public void add(){
        System.out.println("Service add.....");
        userDao.add();
    }
}

@Value :注入普通类型属性

@Service
public class UserService{
    
  @Value(value = "abc")
    private String name;
    public void add(){
        System.out.println("Service add.....");
        System.out.println(name);
    }
}

完全注解开发(没有xml文件)

(1)创建配置类

package com.spring.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

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

}

@Test
    public void test02(){

        //主要是这一行变了
        ApplicationContext context =
                new AnnotationConfigApplicationContext(SpringConfig.class);

        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }

这种方法的优缺点参考
添加链接描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值