(1)Spring的ioc底层原理

Spring的IOC操作

什么是ioc操作?

过去我们用new来创建一个对象,ioc操作则是把对象的创建交给spring进行管理

ioc操作的两种方式
  • 配置文件方式
  • 注解方式

IOC的底层原理

ioc底层原理使用的技术
  1. xml配置文件
  2. dom4j解决xml
  3. 工厂设计模式
  4. 反射
image.png
Spring的bean管理(基于配置文件)

Bean实例化的方式

  • 使用类的无参数构造创建(重点)
  • 使用静态工厂创建
  • 使用实例工厂创建

bean标签常用属性

  • id属性
    给这个bean起一个名字(任意命名),作用context.getBean("id")找到该bean
  • class属性
    创建对象所在类的全路径
  • name属性
    功能和id一样,区别在于id属性不能包含特殊符号,name可以包含(但是name已经不常用了)
  • scope属性
    Bean的作用范围,scope常用属性:
  1. singleton:默认值,单例对象
  2. prototype:多例对象
  3. session:创建对象,放到session
  4. globleSession:创建对象,放到全局session
  5. request:创建对象,把对象放到request域

重点是singleton和prototype

singleton详解
我们在配置文件中配置

    //默认是singleton
    <bean id = "user" class = "User">

在userServlet中创建两个user对象,并输出这两个对象,观察这两个对象的地址

 public static void main(String args[]){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user1 = (User) context.getBean("user");
        User user2 = (User) context.getBean("user");
        System.out.println(user1);
        System.out.println(user2);
    }

输出结果:


image.png

可见,如果使用singleton,创建的是一个对象

prototype详解
同理,在配置文件中加上

 <bean id = "user" class = "User" scope="prototype">
    </bean>

输出结果:


image.png

可见生成了两个对象

属性注入
1.什么时属性注入:创建对象时,向类的属性设置值
2.属性注入的方式:

  • set方法
  • 有参构造注入
  • 接口注入(很少使用)


    image.png

    在spring框架里面,支持前两种方式

Spring中有参构造的属性注入

public class User {
    private String Uname;
    public String getUname() {
        return Uname;
    }


    public User(String uname) {
        this.Uname = uname;
    }
}

配置文件中


    <bean id = "user" class = "User" scope="prototype">
//注意,这里name时指的传入构造函数的参数的名字,所以应该时uname不是Uname        
<constructor-arg name="uname" value="小王八"></constructor-arg>
    </bean>

Spring中set方法实现属性注入(常用)

public class User {
    public String Uname;
    public void setUname(String uname) {
        Uname = uname;
    }
}

    <bean id = "user" class = "User" >
    <property name="Uname" value="小兔子"></property>
         </bean>

注入对象类型属性(重点)
应用场景:Service类中得到Dao的对象,调用Dao的方法
方法:

  1. 在Service中生成Dao类型的属性
  2. 在Service中生成Dao类型属性的set方法
  3. 在配置文件中完成注入关系
public class UserDao {

    public void add(){
        System.out.println("this is dao");
    }
}

public class UserService {

    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    public  void add(){
        System.out.println("this is service");
        userDao.add();
    }

}
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class test {
    public static void main(String args []){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userServlet = (UserService) context.getBean("userService");
        userServlet.add();

    }
}
<!--配置userDao和userServicce对象-->
    <!--注入userDao对象-->
    <bean id = "userDao" class = "UserDao" ></bean>

    <!--注入userService对象-->
    <bean id = "userService" class = "UserService">
        <!--在userService中注入userDao-->
        <!--name :Servic中的属性名    ref: 该属性对应的类的id-->
        <property name="userDao" ref="userDao"></property>
    </bean>

P名称空间注入
1.在beans标签中添加:

 xmlns:p="http://www.springframework.org/schema/p"

Person类如下:

public class Person {

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

    public void Gname(){
        System.out.println(name);
    }
}
  1. 注入Person
<!--p名称空间注入-->
    <bean id="person"  class="Person" p:name="devin"> </bean>

3.测试结果

public class test {
    public static void main(String args []){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = (Person) context.getBean("person");
        person.Gname();
    }
}

image.png

注入复杂类型属性

  1. 数组注入
  2. List注入
  3. Map注入
  4. Properties注入
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class Person {
    private int [] names;
    private List<String> list;
    private Map<String,String> map;
    private Properties properties;
    public void setNames(int[] names) {
        this.names = names;
    }

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

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    public void say(){
        System.out.println(names.length);
        System.out.println(list);
        System.out.println(map);
        System.out.println(properties);
    }
}
<!--复杂数据类型注入-->

    <bean id="person" class="Person">
        <!--数组注入,数组大小是根据配置文件注入了多少个value来决定的
-->
        <property name="names">
            <list>
                <value>1</value>
                <value>2</value>
                <value>2</value>
                <value>2</value>
                <value>2</value>           
            </list>
        </property>
        <!--List注入,和数组一样-->
        <property name="list">
            <list>
                <value>kevin</value>
                <value>kotlin</value>
            </list>
        </property>
        <!--Map注入-->
        <property name="map">
            <map>
                <entry key="123" value="456"></entry>

                <entry key="abc" value="def"></entry>
            </map>
        </property>
        <!--Properties注入-->
        <property name="properties">
            <props>
                <prop key="driver">com.mysql.jdbc.driver</prop>
            </props>
        </property>
    </bean>

输出结果:


image.png
IOC和DI的区别
  • IOC:控制反转,把对象创建交给spring经行配置
  • DI:依赖注入:创建对象的过程中设置对象的属性值
    关系:DI不能单独存在,需在IOC的基础之上完成
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容