Spring-IOC

Spring中的IOC详解 单例Bean和多实例Bean的生命周期主要区别在于实例化和销毁的管理方式,单例Bean在容器启动时创建一个实例,并由容器负责管理其生命周期的完整过程。在Spring框架中,Bean是应用程序的核心组件,它们由Spring容器创建、组装和管理,以帮助开发者实现松耦合、可测试和可维护的代码。IOC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。Bean的自动装配是Spring框架提供的一种便捷的方式,用于自动解析和设置Bean之间的依赖关系,而无需显式配置每一个依赖关系的方式。 阅读详情

关于Spring-IOC,如果有错误,欢迎指正。

Spring-IOC

Spring的体系结构

Spring框架包含众多模块,如Web Servlet、Data Access、Core Container等,其中在Core Container(核心容器)模块中的Core核心模块,提供了Spring框架的基本组成部分,包括了IOC和DI功能。

上图的SpEl指的是Expression Language 模块:是运行时查询和操作对象图的强大的表达式语言。

Spring体系结构详解 (biancheng.net)

IOC和AOP作为Spring框架的核心,我们也要重点去学习。

一、什么是IOC

​ IOC(Inversion of Control)是控制反转是意思,是一种面向对象编程的设计思想。IOC可以把对象的创建和对象之间的调用过程,交给Spring进行管理,从而降低对象之间的耦合度。

二、IOC的底层原理

​ IOC的底层原理:xml解析、工厂模式、反射。

​ IOC实现原理:在工厂模式的基础上,利用xml配置文件,配置创建的对象,然后在工厂类的返回userDao对象的方法中,通过对xml解析获得 userDao 的类路径,再通过反射创建对象,最后返回对象。

​ 这种IOC的过程在工厂模式的基础上进一步降低了耦合度。

三、IOC(接口)

​ 1、IOC思想基于IOC容器完成,IOC容器底层就是对象工厂

​ 2、Spring提供IOC容器实现两种方式:

​ (1)BeanFactory:IOC容器基本实现,是Spring内部使用的接口,不供开发人员使用。

​ (2)ApplicationContext:BeanFactory接口的子接口,有更强大的功能。

在这里插入图片描述

​ BeanFactory与ApplicationContext的区别:

​ BeanFactory在加载配置文件时不会去创建对象,在(获取)使用对象的时候才会创建对象。

​ ApplicationContext在加载配置文件的时候就把配置文件对象进行创建。

​ ApplicationContext虽然会加长项目的启动时间,但在web项目运行时,可以减少加载时间和内存消耗,适合Web开发,推荐使用(耗时耗内存的都在项目启动的时候进行处理更加合适)。

​

​ 3、ApplicationContext接口实现类:

​ (1)ClassPathXmlApplicationContext:

​ 在new的时候需要指定类的路径(src下)

在这里插入图片描述

​ (2)FileSystemXmlApplicationContext

​ 盘的路径(例如:C://file.xml)

在这里插入图片描述

​ 4、BeanFactory

​ ConfigurableApplicationContext:该子接口中可以包括相关的扩展功能

在这里插入图片描述

四、IOC操作

在进行ioc操作之前先在我们的项目中引入spring的基本jar包(核心容器和日志)

在这里插入图片描述

在这里插入图片描述

在项目中导入这5个jar包
在这里插入图片描述

bean管理:

​ 什么是bean管理(两个操作):

​ 1、spring创建对象

​ 2、spring属性注入

bean管理操作(基于xml):

基于xml创建对象:

​ 在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建

​ bean常用属性:

​ (1)id: 唯一标识

​ (2)class: 类全路径(包类路径)

​ (3)name: 和id一样,但是可以增加 / 等特殊符号。

​ 创建对象的时候也是默认执行无参构造方法,完成对象创建

​ 没有无参构造会报错:

xml:

在这里插入图片描述

User:

在这里插入图片描述

基于xm属性注入:

DI:依赖注入,就是注入属性。

1、set方法进行注入:

(1)创建类,定义属性和对应set方法

public class User {
    private int id ;
    private String name;

    public void setId(int id) {
        this.id = id;
    }

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

(2)在spring配置文件中配置对象的创建,配置属性注入

​ 在property标签中注入

<bean id="user" class="com.songzhi.spring.User">
<!--        name的值为类中的属性名,value的值为属性名对应的值(向属性注入的值)-->
        <property name="id" value="123"></property>
        <property name="name" value="刀哥"></property>
</bean>

​ 在User类中加入toString方法:

public void toUserString(){
    System.out.println("UserId = "+id);
    System.out.println("UserName = "+name);
}

​ 测试类进行测试:

@Test
public void testAdd(){
    ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
    User user = context.getBean("user",User.class);
    user.toUserString();
}

​ 输出效果:
在这里插入图片描述

2、有参构造进行注入:

(1)创建类,定义属性,创建属性对应有参构造方法:

public class User {
    private int id ;
    private String name;

    User(int id ,String name){
        this.id=id;
        this.name=name;
    }
    public void toUserString(){
        System.out.println("UserId = "+id);
        System.out.println("UserName = "+name);
    }
}

(2)在spring配置文件中进行配置

<bean id="user" class="com.songzhi.spring.User">
    <constructor-arg name="id" value="1"></constructor-arg>
    <constructor-arg name="name" value="小明"></constructor-arg>
</bean>

测试类与上面set方法测试类相同,输出结果:toset
在这里插入图片描述

3、p名称空间注入:

​ 使用p名称空间注入,可以简化基于xml配置方式

(1)添加p名称空间在配置文件中:

​

<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
	
</beans>

(2)进行属性注入,在bean标签里面进行操作:

<bean id="user" class="com.songzhi.spring.User"
    p:id="2" p:name="小红">
</bean>

注意:这种方式底层用的是set方法进行注入!!!

这次使用上面set方法进行注入的类,测试类也是用set方法进行注入的测试类。toset

输出结果:
在这里插入图片描述

xml注入其他类型属性:
1、字面量:

(1)NULL值

对user的name属性注入null:

<bean id="user" class="com.songzhi.spring.User">
    <property name="id" value="0"></property>
    <property name="name">
        <null/>
    </property>
</bean>

测试类和user类与上面set方法注入相同toset

输入结果:

在这里插入图片描述

(2)属性值包含特殊符号:

如果赋值中含有特殊符号有两种方式进行属性注入:

第一种:使用转义字符(&lt; &gt;)=>(< >)

<bean id="user" class="com.songzhi.spring.User">
    <property name="id" value="0"></property>
    <property name="name" value="&lt;&gt;">
    </property>
</bean>

测试类和user类与上面set方法注入相同toset

输出结果:
在这里插入图片描述

第二种:把带特殊符号内容写到CDATA当中去:(<![CDATA[特殊符号内容]]>)

<bean id="user" class="com.songzhi.spring.User">
    <property name="id" value="0"></property>
    <property name="name">
        <value><![CDATA[<&*()>]]></value>
    </property>
</bean>

测试类和user类与上面set方法注入相同toset

输出结果:
在这里插入图片描述

2、注入属性-外部bean

如下图结构创建类和接口:

在这里插入图片描述

其中,UserDaoImpl类:

public class UserDaoImpl implements UserDao {

    @Override
    public void update() {
        System.out.println("UserDaoImpl update ......");
    }
}

UserDao类:

public interface UserDao {

    void update();

}

UserService类:

在service类中调用dao里面的方法。

public class UserService {
    private UserDao userDao;

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

配置文件:

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

测试类:

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

输出结果:

在这里插入图片描述

这种spring的方式可以实现在Service的add方法中调用daoimpl中的方法。

原始的做法可以在add中加入:

UserDao userDao = new UserDaoImpl();
userDao.update();

这样利用多态也可以做到在service的方法中调用接口实现类的方法。

3、注入属性-内部bean:

(1)现在有一对多的关系:

​ 部门和员工,一个部门有多个员工,一个员工属于一个部门。

​ 一:部门,多:员工

(2)在实体类中表示一对多的关系:

/**
 * 部门类
 */
public class Dept {
    private String DName;

    public void setDName(String DName) {
        this.DName = DName;
    }
    @Override
    public String toString() {
        return "Dept{" +
                "DName='" + DName + '\'' +
                '}';
    }
}
/**
 * 员工类
 */
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;
    }
    @Override
    public String toString() {
        return "Emp{" +
                "EName='" + EName + '\'' +
                ", gender='" + gender + '\'' +
                ", dept=" + dept.toString() +
                '}';
    }
}

(3)在spring配置文件中进行配置:

<bean id="emp" class="com.songzhi.spring.entity.Emp">
    <property name="EName" value="Li"></property>
    <property name="gender" value="女"></property>
    <property name="dept">
        <bean id="dept" class="com.songzhi.spring.entity.Dept">
            <property name="DName" value="技术部"></property>
        </bean>
    </property>
</bean>

测试类:

@Test
public void testOne(){
    ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
    Emp emp = context.getBean("emp",Emp.class);
    System.out.println(emp.toString());

}

输出结果:
在这里插入图片描述

4、注入属性-级联赋值:

第一种写法:外部bean:

<bean id="emp" class="com.songzhi.spring.entity.Emp">
    <property name="EName" value="wan"></property>
    <property name="gender" value="男"></property>
    <!--级联赋值-->
    <property name="dept" ref="Dept"></property>
</bean>
<bean id="Dept" class="com.songzhi.spring.entity.Dept">
    <property name="DName" value="安保部"></property>
</bean>

其他部分与上面一样:toOthers

输出结果:
在这里插入图片描述

第二种写法:使用对象.属性的方式

这种方式会调用类中的get方法,所以我们要先在Emp类中生成get方法

public Dept getDept() {
    return dept;
}

xml:

<bean id="emp" class="com.songzhi.spring.entity.Emp">
    <property name="EName" value="lin"></property>
    <property name="gender" value="男"></property>

    <property name="dept" ref="dept"></property>
    <property name="dept.DName" value="财务部"></property>
</bean>
<bean id="dept" class="com.songzhi.spring.entity.Dept">
    <property name="DName" value="安保部"></property>
</bean>

输出内容:

在这里插入图片描述

5、注入集合属性:

注入包括:数组类型,list集合类型,map集合类型

(1)创建类,定义数组、list、map、set,生成对应的set方法

public class Stu {
    //数组
    private String[] courses;
    //集合
    //list
    private List<String> lists;
    //map
    private Map<String,String> maps;
    //set
    private Set<String> sets;

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

    public void setLists(List<String> lists) {
        this.lists = lists;
    }

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

    public void setSets(Set<String> sets) {
        this.sets = sets;
    }
    
    @Override
    public String toString() {
        return "Stu{" +
                "courses=" + Arrays.toString(courses) +
                ", lists=" + lists +
                ", maps=" + maps +
                ", sets=" + sets +
                '}';
    }
}

(2)在spring配置文件中进行配置

数组类型可以使用list标签或者array标签进行注入。

<bean id="stu" class="com.songzhi.spring.entity.Stu">
    <!--注入数组-->
    <property name="courses">
        <array>
            <value>数学</value>
            <value>英语</value>
        </array>
    </property>
    <!--注入list-->
    <property name="lists">
        <list>
            <value>60分</value>
            <value>90分</value>
        </list>
    </property>
    <!--注入map-->
    <property name="maps">
        <map>
            <entry key="JAVA" value="java"></entry>
            <entry key="Python" value="python"></entry>
        </map>
    </property>
    <!--注入set-->
    <property name="sets">
        <set>
            <value>体育部长</value>
            <value>学生会长</value>
        </set>
    </property>
</bean>

(3)测试类:

@Test
public void testTwo(){
    ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
    Stu stu =context.getBean("stu",Stu.class);
    System.out.println(stu.toString());
}

输出结果:

在这里插入图片描述

细节:

在list集合中放入对象类型:

实体类:

public class Teacher {
    private List<Course> courses;

    public void setCourses(List<Course> courses) {
        this.courses = courses;
    }
    public void toTeacherString(){
        for (Course course : courses) {
            System.out.println(course.toString());
        }
    }
}
public class Course {
    private String cname;

    public void setCname(String cname) {
        this.cname = cname;
    }
    @Override
    public String toString() {
        return "Course{" +
                "cname='" + cname + '\'' +
                '}';
    }
}

配置文件:

<bean id="teacher" class="com.songzhi.spring.entity.Teacher">
    <property name="courses">
        <list>
            <ref bean="course1"/>
            <ref bean="course2"/>
        </list>
    </property>
</bean>
<bean id="course1" class="com.songzhi.spring.entity.Course">
    <property name="cname" value="JAVA"></property>
</bean>
<bean id="course2" class="com.songzhi.spring.entity.Course">
    <property name="cname" value="TypeScript"></property>
</bean>

test类:

@Test
public void testThree(){
    ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
    Teacher teacher = context.getBean("teacher",Teacher.class);
    teacher.toTeacherString();
}

在这里插入图片描述

注意:

内部的property只能在当前bean中使用,需要把里面的property分别抽取出来,作为公共部分来使用。

把集合注入部分提取出来:

(1)在spring配置文件中引入名称空间util

新建一个bean.xml,引入名称空间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/beans
       http://www.springframework.org/schema/beans/spring-util.xsd">
        

</beans>

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

<bean id="stu" class="com.songzhi.spring.entity.Stu">
    <!--注入数组-->
    <property name="courses" ref="course"/>
    <!--注入list-->
    <property name="lists" ref="list"/>
    <!--注入map-->
    <property name="maps" ref="map"/>
    <!--注入set-->
    <property name="sets" ref="set"/>
</bean>

<util:list id="course">
    <value>数学</value>
    <value>英语</value>
</util:list>

<util:list id="list">
    <value>60分</value>
    <value>90分</value>
</util:list>

<util:map id="map">
    <entry key="JAVA" value="java"></entry>
    <entry key="Python" value="python"></entry>
</util:map>

<util:set id="set">
    <value>体育部长</value>
    <value>学生会长</value>
</util:set>

这样的话就可以在公共使用值了

6、FactoryBean

FactoryBean是Spring容器提供的一种可以扩展容器对象实例化逻辑的接口,与BeanFactory不同,这里的Bean是生产对象的工厂。

应用场景:

​ FactoryBean 通常是用来创建比较复杂的bean,一般的bean 直接用xml配置即可,但如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,用xml配置比较困难,这时可以考虑用FactoryBean。

Spring中有两种bean:普通bean和工厂bean

普通bean:

在配置文件中定义bean类型就是返回类型

工厂Bean:

在配置文件中定义bean类型可以和返回类型不一样

​ 工厂bean中的三个方法:

public String getObject() throws Exception:该方法返回该FactoryBean“生产”的对象。我们需要实现该方法以给出自己对象实例化逻辑

public Class<?> getObjectType():该方法仅返回getObject()方法所返回的对象的类型。如果预先无法确定,则返回null

public boolean isSingleton() :该方法返回结果用于表明,getObject()“生产”的对象是否要以singleton(单例)形式存于容器中。如果以singleton形式存在,则返回true,否则返回false

第一步:创建类,让这个类作为工厂Bean,实现接口FactoryBean

public class MyBean implements FactoryBean<Course> {
    @Override
    public Course getObject() throws Exception {
        return null;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }
}

在getObject方法中可以定义返回bean

第二步:实现接口里面的方法,在实现的方法中定义返回的bean类型:

@Override
public Course getObject() throws Exception {
    Course course = new Course();
    course.setCname("abc");
    return course;
}

xml:

<bean id="myBean" class="com.songzhi.spring.Bean.MyBean">
    </bean>

测试类:

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

实体类:

public class Course {
    private String cname;

    public void setCname(String cname) {
        this.cname = cname;
    }

    @Override
    public String toString() {
        return "Course{" +
                "cname='" + cname + '\'' +
                '}';
    }
}

输出结果:

在这里插入图片描述

Bean的作用域以及生命周期:
作用域:

在Spring里面,设置bean实例是单实例还是多实例:

Spring中,默认情况下bean是单实例对象:

@Test
public void test1(){
    ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
    Course course1 = context.getBean("course",Course.class);
    Course course2 = context.getBean("course",Course.class);
    System.out.println(course1);
    System.out.println(course2);
}
public class Course {
    private String cname;

    public void setCname(String cname) {
        this.cname = cname;
    }
}
<bean id="course" class="com.songzhi.spring.entity.Course">
    <property name="cname" value="123"/>
</bean>

输出结果:

在这里插入图片描述

由此可见默认是单实例模式,两个对象输出的地址相同。

设置单实例和多实例的方法:

在spring配置文件bean标签里面有属性(scope)用于 设置单实例还是多实例:

在这里插入图片描述

prototype是多实例,singleton是单实例。

在bean标签中设置多实例:

<bean id="course" class="com.songzhi.spring.entity.Course" scope="prototype">
    <property name="cname" value="123"/>
</bean>

设置多实例之后的输出:
在这里插入图片描述

singleton和prototype的区别:

第一个singleton是单实例prototype是多实例;

第二个设置scope是singleton是时候,加载spring配置文件的时候就会创建单实例的对象;

设置scope是prototype的时候,不是在加载spring配置文件的时候创建对象,在调用getBean方法的时候创建多实例对象;

下面两个类型只适用于web程序:

request:表示一次请求,每次创建对象会放进request对象当中。

session:一次会话,每次创建对象会放进session对象当中。

关于scope其他类型的详细介绍:

spring中的scope详解 - 山高我为峰 - 博客园 (cnblogs.com)

bean生命周期(7步):

从对象创建到对象销毁的过程叫做生命周期(创建、注入、初始化、使用、销毁)

(1)通过构造器创建bean实例(无参数构造):

public class Life {

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

(2)为bean 的属性设置值,和对其他bean 的引用(调用set方法)

public class Life {

    private String LifeName;

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

    public void setLifeName(String lifeName) {
        LifeName = lifeName;
        System.out.println("第二步:调用set方法设置属性值。");
    }
}

(3)调用bean 的初始化的方法(需要进行配置初始化的方法)

在life中定义销毁的方法:

public void initMethod(){
    System.out.println("第三步:执行初始化的方法。");
}

在xml中引入:

<bean id="life" class="com.songzhi.spring.Bean.Life" init-method="initMethod">
    <property name="lifeName" value="lifeName的value"></property>
</bean>

(4)bean可以使用了(对象获取到了)

@Test
public void testLife(){
    ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
    Life life = context.getBean("life",Life.class);
    System.out.println("第四步:获取创建bean实例化对象");
    System.out.println("使用life中:"+life);
    //手动销毁bean实例
    ((ClassPathXmlApplicationContext)context).close();
}

(5)当容器关闭的时候,调用bean中销毁的方法(需要进行配置销毁的方法)

手动创建销毁的方法:

public void destroyMethod(){
    System.out.println("第五步:执行销毁的方法。");
}

xml中引入:

<bean id="life" class="com.songzhi.spring.Bean.Life" init-method="initMethod" destroy-method="destroyMethod">
    <property name="lifeName" value="lifeName的value"></property>
</bean>

在测试类中手动销毁bean实例:

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

测试结果:

在这里插入图片描述

上面一共是5步,算上下面的后置处理器是七步:

bean的后置处理器:把bean实例传递bean后置处理器的方法,此方法在初始化分别前后,有两个方法

一个是postProcessBeforeIntialization

一个是postProcessAfterIntialization

后置处理器:

创建MyBeanPost类:

public class MyBeanPost implements BeanPostProcessor {

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

}

在xml中配置后置处理器:

<bean id="myBeanPost" class="com.songzhi.spring.Bean.MyBeanPost"></bean>

输出结果:

在这里插入图片描述

第一步:执行无参构造创建bean实例。
第二步:调用set方法设置属性值。
第三步:在初始化之前执行的方法。
第四步:执行初始化的方法。
第五步:在初始化之后执行的方法。
第六步:获取创建bean实例化对象
使用bean
第七步:执行销毁的方法。

xml方式的自动装配:

什么是自动装配:

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

基于xml文件的自动装配:byType(类型),byName(名称), constructor(构造函数)

自动装配过程:

根据属性名称自动注入(byName):

<bean id="emp" class="com.songzhi.spring.entity.Emp" autowire="byName"></bean>
<bean id="dept" class="com.songzhi.spring.entity.Dept" ></bean>

设置属性为byName,那么spring会根据class属性找到对应实体类,然后查询实体类中所有的set方法的名字,根据set方法后面的名字(比如setName方法后面的名字就是Name)再到配置文件中寻找一个与该名字相同id的bean(id=“Name”),注入进来。

根据属性类型进行自动注入(byType):

<bean id="emp" class="com.songzhi.spring.entity.Emp" autowire="byType"></bean>
<bean id="dept" class="com.songzhi.spring.entity.Dept" ></bean>

设置autowire属性为byType,那么Spring会自动寻找一个与该属性类型相同的Bean(class值中"."的最后一个,例如class="com.songzhi.spring.entity.Emp"的类型就是Emp),注入进来。

*注意:使用byType这种方式,必须保证配置文件中所有bean的class属性的值是唯一的,否则就会报错。(就是xml中的bean标签的class的值必须都不一样)。

外部属性文件:

直接配置数据库信息:

引入德鲁伊jar包:

在这里插入图片描述

配置德鲁伊连接池;

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

引入外部属性文件配置数据库连接池:

(1)创建外部属性文件properties格式文件,数据库连接信息

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

等号前面的名字可以随便写,但为了防止名称冲突使用prop点的方式命名

(2)把外部的properties文件引入到spring配置文件中来:

引入context名称空间

<?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
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
        ">

在spring配置文件中使用标签引入外部配置文件

<!--    在spring配置文件中使用标签引入外部配置文件-->
    <context:property-placeholder location="classpath:Application.properties"/>
<!--    配置连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${prop.driverClass}"/>
        <property name="url" value="${prop.url}"/>
        <property name="username" value="${prop.username}"/>
        <property name="password" value="${prop.password}"/>
    </bean>

IOC(bean管理)基于注解:

1、什么是注解:

(1)注解是代码特殊标记

​ 格式:@注解名( 属性名=属性值,属性名=属性值,。。。)

(2)注解在什么什么时候用:

​ 类上面、方法上面、属性上面

(3)使用注解的目的

​ 简化xml配置

2、Spring针对Bean管理中创建对象提供注解:
  • @Component
    • 普通注解,创建对象
  • @Service
    • 用在业务逻辑层/Service层上
  • @Controller
    • 用在Web层上
  • @Repository
    • 用在Dao层或Mapper上
  • 上面四个注解功能是一样的,都可以用来创建bean
3、基于注解方式实现对象的创建:
1、引入依赖:

在这里插入图片描述

2、开启组件扫描:
<?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
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
        ">

<!--    开启组件扫描,如果扫描多个包,多个包使用逗号隔开-->
<!--    扫描包上层目录-->
    <context:component-scan base-package="com.songzhi"/>

</beans>
3、创建类,在类上面添加创建对象注解:
/**
 * 在注解里面value属性值可以省略不写
 * 默认是类名称,首字母小写
 */
@Component(value = "manService")
public class ManService {
    public void add(){
        System.out.println("ManService add......");
    }
}
4、开启组件扫描细节配置:

1、

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

2、

<!--    下面配置扫描包所有内容-->
<!--    context:exclude-filter: 设置哪些内容不进行扫瞄-->
    <context:component-scan base-package="com.songzhi">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
5、基于注解方式实现属性注入:

@AutoWired

根据属性类型自动注入

1、把service和dao对象创建,在service和dao类添加创建对象注解

2、在service注入dao对象,在service类添加dao类型属性,在属性上面使用注解

<context:component-scan base-package="com.songzhi" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
@Component
public interface UserDao {

    void update();

}
@Service
public class UserService {

    @Autowired
    private UserDao userDao;

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

@Qualifier

根据属性名称注入

这个注解的使用要和上面的Autowired一起使用

@Service
public class UserService {

    @Autowired//根据类型进行注入
    @Qualifier(value = "userDaoImpl")//根据名称进行注入
    private UserDao userDao;

    public void add(){
        System.out.println("service add ......");
        userDao.update();
    }
}
@Component
public class UserDaoImpl implements UserDao {

    @Override
    public void update() {
        System.out.println("UserDaoImpl update ......");
    }
}

@Resource(Javax)

根据属性类型和属性名称注入

只写resource默认根据类型进行注入

<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
//    @Resource//根据类型进行注入
    @Resource(name = "userDao")//根据名称进行注入
    private UserDao userDao
@Repository(value = "userDao")
public class UserDaoImpl implements UserDao {

    @Override
    public void update() {
        System.out.println("UserDaoImpl update ......");
    }
}

@Repository(value=“userDao”)注解是告诉Spring,让Spring创建一个名字叫“userDao”的UserDaoImpl实例。
当Service需要使用Spring创建的名字叫“userDao”的UserDaoImpl实例时,就可以使用@Resource(name = “userDao”)注解告诉Spring,Spring把创建好的userDao注入给Service即可。
@Repository原文链接:https://blog.youkuaiyun.com/weixin_39426138/article/details/77679912

Value

注入普通类型属性

@Value(value = "abc")
private String name;
6、完全注解开发:

(1)创建配置类,替代xml配置文件

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

}

(2)编写测试类

@Test
public void test6(){
    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    UserService userService = context.getBean("userService",UserService.class);
    System.out.println(userService);
    userService.add();

}

其他类:

@Service
public class UserService {

//    @Autowired//根据类型进行注入
//    @Qualifier(value = "userDaoImpl")//根据名称进行注入
//    @Resource//根据类型进行注入
    @Resource(name = "userDao")//根据名称进行注入
    private UserDao userDao;

    @Value(value = "abc")
    private String name;

    public void add(){
        System.out.println("注入的name的值为:"+name);
        System.out.println("service add ......");
        userDao.update();

    }
}
@Component
public interface UserDao {

    void update();

}
@Repository(value = "userDao")
public class UserDaoImpl implements UserDao {



    @Override
    public void update() {
        System.out.println("UserDaoImpl update ......");
    }
}

输出结果:
在这里插入图片描述

学习源自:尚硅谷Spring框架视频教程(spring5源码级讲解)_哔哩哔哩_bilibili

Spring官网:Spring | Home

(1)创建配置类,替代xml配置文件

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

}

(2)编写测试类

@Test
public void test6(){
    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    UserService userService = context.getBean("userService",UserService.class);
    System.out.println(userService);
    userService.add();

}

其他类:

@Service
public class UserService {

//    @Autowired//根据类型进行注入
//    @Qualifier(value = "userDaoImpl")//根据名称进行注入
//    @Resource//根据类型进行注入
    @Resource(name = "userDao")//根据名称进行注入
    private UserDao userDao;

    @Value(value = "abc")
    private String name;

    public void add(){
        System.out.println("注入的name的值为:"+name);
        System.out.println("service add ......");
        userDao.update();

    }
}
@Component
public interface UserDao {

    void update();

}
@Repository(value = "userDao")
public class UserDaoImpl implements UserDao {



    @Override
    public void update() {
        System.out.println("UserDaoImpl update ......");
    }
}

输出结果:

在这里插入图片描述

学习源自:尚硅谷Spring框架视频教程(spring5源码级讲解)_哔哩哔哩_bilibili

Spring官网:Spring | Home

Spring Ioc实现机制——简析 需要明确一点,任何项目没有了Spring,也依旧能做,那么为什么Spring还会这么火?答案就是Spring的两个特性IoC与AOP,这里需要指出的是,并不是Spring提出的AOP的概念,只能说是Spring很好的实现了AOP的特性。那么,这次就先讨论下Spring IoC的实现机制。  IoC是什么东东? IoC实现的机制是什么样子的? 模拟一个Spring IoC的实现 阅读详情

相关推荐

多尺度变换(Multidimensional Scaling ,MDS)详解

介绍多尺度变换基本原理

5215

Spring中IOC详解

一、IOC的原型 IOC ----控制反转 比如我们有一个功能是获取用户数据,我们使用Dao层实现这个功能,再在Service层调用这个功能。但是我们每增加一个接口,比如获取mysql中的数据,就要修改原来的代码,如果再增加一个新的接口,又需要去service实现类中修改对应的实现。 解决方法 用户实际调用的是业务层,dao层他们不需要接触 UserServiceImpl userService = new UserServiceImpl(); userSe

qq_41359998的博客 1万+

期货套利策略(二)

接上一篇期货套利策略,随着对期货套利策略的深入了解,我发现套利策略不是那么好做的。下面将会讲碰到的一些问题。 上一篇文章中没有考虑滑点的问题,这里我们把滑点问题考虑进去。这里先说一些天勤api的买入点,天琴的买入点是当前K线的收盘价。碰到数据传输问题,还有计算等各方面问题,实际情况是无法在当前K线的收盘价买入的。这里我们把这方面问题考虑进去,利用api.wait_update()调到下一个k线数据...

qq_31611005的博客 1712

SpringIOC机制详解

所谓Bean的作用域其实就是指Spring给我们创建出的对象的存活范围,在配置文件中通过bean的scope属性指定取值范围说明singleton默认值,单例的prototype多例的requestWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中sessionWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中。

互联网底层民工的博客 9561

地平线RDKX3初始配置与USB无线网卡

地平线X3无线网卡配置

Richard_Mei的博客 4077

Ubuntu Server 24.04 安装 (超详细)

本文介绍最小化安装 Ubuntu Server的详细过程。

炀炀的专栏 1万+

Spring IoC详解

Spring 是一个开源的Java框架,它提供了丰富的功能和组件,用于简化企业级应用程序的开发。Spring 框架提供了依赖注入、面向切面编程、事务管理、数据访问等功能,是一个全面的企业应用开发解决方案。Spring MVC 是 Spring 框架中的一个模块,即Spring功能的一部分,用于构建 Web 应用程序的 MVC(Model-View-Controller)架构。Spring MVC 提供了基于注解的方式来定义控制器、处理请求和渲染视图,使得开发 Web 应用程序更加简单和灵活。

2303_78892316的博客 5008

SAP UI5 OData V4 操作结果访问:从 getObject 到返回值上下文与 $$inheritExpandSelect

SAP UI5 OData V4 操作结果获取指南 摘要:在 SAP UI5 OData V4 模型中,操作结果需通过绑定上下文获取而非直接从 invoke() 返回。本文详解核心要点: 数据获取路径 使用 invoke() 发起请求后,通过 getBoundContext().getObject() 获取结果 特定场景下 invoke() 可能返回返回值上下文(如草稿切换) 关键实践技巧 使用 $$inheritExpandSelect 继承字段选择,避免二次读取 对象页应用中,通过替换绑定上下文实现无缝

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 314

Spring框架(IOC)

一、什么是 IOC (1)控制反转,把对象创建和对象之间的调用过程,交给 Spring 进行管理 (2)使用 IOC 目的:为了耦合度降低 二、IOC 底层原理 xml 解析、工厂模式、反射 三、IOC过程 xml解析帮助我们得到xml文件中我们需要的属性值 利用这个属性值配和下面的class类的两个方法创建出我们需要的对象(返回前做类型强转) 三、BeanFactory 接口 IOC 思想基于 IOC 容器完成,IOC 容器底层就是对象工厂 Spring 提供 IOC 容器实现两种方式:(两个接口)

eyvr的博客 4204

eNSP常见故障处理

eNSP无法启动设备一直停在#井号的问题的解决方案?

lvshiliang123的博客 2万+

YOLOv8实战教程:从模型训练到改进的全流程指南

回顾这段YOLOv8的实战历程,从最初的模型训练到后来的各种改进尝试,我深刻体会到目标检测技术的魅力与挑战。YOLOv8作为一款优秀的框架,不仅易用性强,而且具备很强的可扩展性,让我能在其基础上不断创新。未来,我计划在以下几个方向继续探索:一是将YOLOv8与多模态技术结合,尝试实现图像与文本的联合目标检测;二是深入研究自监督学习在YOLOv8中的应用,减少对标注数据的依赖;三是探索YOLOv8在更广泛场景的部署,如机器人、自动驾驶等。

LXY_LOVE36的博客 279

【javaEE】Spring IOC

容器是⽤来容纳某种物品的(基本)装置。(有点废话)我们想想,之前课程我们接触的容器有哪些?• List/Map->数据存储容器• Tomcat->Web容器那么Spring也作为一个容器,装的是对象(Bean)这里的Bean跟在Java基础语法中是不一样的,在Javase中Bean指的是实体类,比如Student类在JavaEE进阶中,Bean指的是Spring管理的对象。

mr_yuanshen的博客 1300

如何在Ubuntu 22.04系统上安装CUDA 12.9

本文提供Ubuntu22.04系统上安装CUDA12.9的简明指南:1)确认已安装适配575驱动;2)清理旧版本后安装必需依赖库;3)通过deb包方式添加英伟达源并安装CUDA12.9工具包;4)配置环境变量;5)通过nvcc-V和nvidia-smi命令验证安装。文中包含常见问题解决方法及多显卡使用说明,全程约需10分钟完成安装。

2501_93651177的博客 1481

Spring IOC

合并 Bean 定义,对父类的定义进行合并和覆盖,如果父类还有父类,会进行递归合并,以获取完整的 Bean 定义信息。如果是方法调用是不算循环依赖的,循环依赖必须要持有引用。实际开发中,我们如果在对象 A 内部去创建、修改或者注销另一个对象 B,这会导致对象之间非常复杂的依赖关系,不利于代码的维护更新。比如我们直接在上层类内调用了底层类的构造方法,一旦底层类的构造方法发生改变,就必须修改所有上层类的代码。设值注入:依赖的对象通过 setter 方法传入的,对象已经实例化,发生属性填充和依赖注入的时候。

2401_84881237的博客 1646

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Spring——IOC

Spring是容器(可以管理所有的组件(类))框架什么是容器(Container): 从程序设计角度看就是封装对象的对象,因为存在放入、拿出等操作,所以容器还要管理对象的生命周期,如Tomcat就是Servlet和JSP的容器;为什么说Spring是一个一站式的轻量级开源框架呢?​ 轻量级:不是指Spring框架的模块少,数量很轻,而是Spring的优点Spring的体系结构图核心容器:提供了框架的基本组成部分,包括 IOC 和依赖注入功能。

会奔跑的茄子的博客 764

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Spring IoC 详解

IoC即控制反转(Inversion of Control),也被称为依赖倒置原则,是设计模式六大原则之一。其核心思想是程序应依赖抽象接口,而非具体实现,从而降低代码间的耦合度。依赖注入(DI):不通过类内部直接创建依赖对象,而是将外部创建好的依赖对象通过构造函数或参数传递给类使用。依赖查找:受控对象通过容器 API 查找所需资源和协作对象。谁控制谁,控制什么:传统编程中,对象由程序主动创建;而 IoC 中,对象由容器控制创建,容器负责管理外部资源获取。为何反转,哪些方面反转。

YT的博客 1455

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Spring IoC

loC是Spring的核心思想其实loC我们在前面已经使用了,在类上面添加和注解,就是把这个对象交给Spring管理,Spring 框架启动时就会加载该类.把对象交给Spring管理,就是loC思想.IoC:(控制反转)也就是说 Spring 是⼀个"控制反转"的容器什么是控制反转呢?也就是控制权反转.什么的控制权发生了反转?获得依赖对象的过程被反转了也就是说,当需要某个对象时,传统开发模式中需要自已通过new创建对象,现在不需要再进行创建,把创建对象的任务交给容器,程序中只需要依赖注入。

2401_83177222的博客 1392

spring IOC的理解

是一个对象创建和依赖管理的设计模式。原来对象是由开发者来进行控制的,有了spring后,可以把对象交给spring来帮我们管理。使用IOC时,直接告诉框架,我需要哪些东西,然后spring框架创建,然后我们再拿出来用就行。IOC创建对象的方式:基于XML(少的很)和基于注解(配置类,扫描包)

2301_77574331的博客 1149

Spring IoC - Spring IoC 的设计

前言 本文为解读Spring IoC 模块源码的开篇介绍。介绍Spring IoC 的相关概念与设计。 What is IoC 控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency...

Richard Program Studio 401

Spring IOC详解

什么是Bean。

杰尼龟的小龟壳的博客 1138

Spring IOC 过程

原创出处 http://www.jianshu.com/p/17b66e6390fd 「莫那一鲁道」欢迎转载,保留摘要,谢谢! 1. 广义的 IOC 2. Spring 的 IoC 3. 总结 1. 广义的 IOC IoC(Inversion of Control) 控制反转,即“不用打电话过来,我们会打给你”。 两种实现: 依赖查找(DL)和依赖注入(DI)。 IOC 和 DI 、DL...

a925907195的专栏 1233

Spring IoC &DI入门

IoC是Spring的核心思想,其实IoC我们已经使用过了,在类上添加@Rest Controller和@Controller注解,就是将这个对象交给Spring管理,Spring框架启动时就会加载该类,把对象交给Spring处理,就是IoC思想。概念:IoC (Inversion of Control) 即控制反转,是⾯向对象编程中的⼀种设计原则。主要是通过第三⽅IoC容器,对Bean对象进⾏统⼀管理,及组织对象之间的依赖关系。获得依赖对象的过程,由原本程序⾃⼰控。

wuyunhang123456的博客 899
上一篇: 正则表达式(JAVA)【提升字符串处理能力的利器】
下一篇: C#委托(1基础)
吊云
博客等级 码龄6年 73粉丝 10原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值