Spring基本操作和原理(复习笔记之IOC)

概念

针对bean的生命周期进行管理的轻量级容器,提供了功能强大IOC、AOP及Web MVC等功能

IOC

控制反转,DI依赖注入,将创建对象的过程交给spring管理

AOP

动态代理,在不修改源码的情况下修改或添加功能

特点
1.方便解耦,简化开发
2.Aop编程支持
3.方便测试
4.方便整合各种框架
5.方便进行事务操作
6.降低javaEE API开发难度(例如jdbc)

在这里插入图片描述

入门

在这里插入图片描述

创建实体类

package com.zwj.bean;

/**
 * @author zwj
 * @date 2022/2/14 - 21:27
 */
public class User {

    private int id;
    private String name;

    public void add(){
        System.out.println("add被调用...............");
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

配置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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean class="com.zwj.bean.User" id="user"></bean>

</beans>

使用ClassPathXmlApplicationContext类读取配置文件

package com.zwj;

import com.zwj.bean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author zwj
 * @date 2021/7/11 - 15:16
 */
public class SpringText {

    @Test
    public void text1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = context.getBean("user", User.class);
        user.add();
    }

}

IOC概念和原理

概念

什么是Ioc
1.控制反转,把对象创建和对象调用的过程交给spring进行管理
2.使用ioc目的:降低耦合度
底层原理
	xml解析,工厂模式,反射

原理

Ioc过程
在这里插入图片描述

Ioc实现(工厂模式)

Ioc底层就是一个对象工厂,Spring提供Ioc容器实现的两种方式

1.BeanFactory
	Ioc容器基本实现,Spring内部使用的接口,一般开发人员不使用,加载配置文件时,不会创建对象,使用时才会创建
2.ApplicationContext
	BeanFactory的子接口,提供更多的功能,提供给开发人员使用的,加载配置文件,创建对象,使用getBean("id",Class)加载工厂模式返回确定类型的对象
3.ApplicationContext实现类
	1) FileSystemApplicationContext(path) //path为绝对路径
	2) ClassPathXmlApplicationContext(path) //path 为当前src下的相对路径

Bean管理xml的方式

创建对象
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">

    <bean class="com.zwj.bean.User" id="user">
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
    </bean>

</beans>
有参构造注入属性(constructor-arg)
# 前提是实体类中要声明相应的构造方法
    <!--构造方法注入属性-->
    <bean class="com.zwj.bean.User" id="user">
        <constructor-arg name="id" value="1"></constructor-arg>
        <constructor-arg name="name" value="张三"></constructor-arg>
    </bean>
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"
       # 特定的名称空间并不需要定义在一个XSD文件中,它只在Spring内核中存在。p名称空间就是这样,它不需要一个schema定义
       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">

    <!--set方法注入属性-->
<!--    <bean class="com.zwj.bean.User" id="user">-->
<!--        <property name="id" value="1"></property>-->
<!--        <property name="name" value="张三"></property>-->
<!--    </bean>-->
    <!--构造方法注入属性-->
<!--    <bean class="com.zwj.bean.User" id="user">-->
<!--        <constructor-arg name="id" value="1"></constructor-arg>-->
<!--        <constructor-arg name="name" value="张三"></constructor-arg>-->
<!--    </bean>-->

    <!--p名称空间set注入属性-->
    <bean class="com.zwj.bean.Book" id="book" p:bookName="九阳真经"></bean>

</beans>
c命名空间
和p命名空间类似,用于构造函数注入属性
注入空值和特殊符号
    <bean class="com.zwj.bean.Book" id="book" p:bookName="九阳真经">
        <!--设置空值-->
        <property name="author">
            <null/>
        </property>
        <!--设置特殊字符
            1.转移字符 &lt; &gt;
            2.使用CDATA
        -->
        <property name="address">
            <value>
                <![CDATA[<<南京>>]]>   # xml文件中的写法
            </value>
        </property>
    </bean>
注入外部bean
# dao
public class BeanDaoImpl {

    public void insert(){
        System.out.println("insert bean。。。。。。");
    }

}
# service
public class BeanServiceImpl {

    private BeanDaoImpl beanDao;

    public BeanServiceImpl(BeanDaoImpl beanDao) {
        this.beanDao = beanDao;
    }

    public void add(){
        beanDao.insert();
    }
}
# xml
    <!--注入外部bean-->
    <bean id="beanDao" class="com.zwj.dao.BeanDaoImpl"></bean>
    <bean id="beanService" class="com.zwj.service.bean.BeanServiceImpl">
        <constructor-arg name="beanDao" ref="beanDao"></constructor-arg>
    </bean>
注入内部Bean
# 在内部注入bean
    <!--内部Bean-->
    <bean id="emp" class="com.zwj.bean.Emp">
        <property name="empName" value="lucy"></property>
        <property name="gender" value="female"></property>
        <property name="dept">
            <bean id="dept" class="com.zwj.bean.Dept" p:deptName="安保部"></bean>
        </property>
    </bean>
级联赋值
# 在内部注入bean 级联赋值
    <!--内部Bean-->
    <bean id="emp" class="com.zwj.bean.Emp">
        <property name="empName" value="lucy"></property>
        <property name="gender" value="female"></property>
        <property name="dept">
            <bean id="dept" class="com.zwj.bean.Dept" p:deptName="安保部"></bean>
        </property>
    </bean>
# 外部bean,级联赋值
    <!--级联赋值-->
    <bean id="emp" class="com.zwj.bean.Emp">
        <property name="empName" value="lucy"></property>
        <property name="gender" value="female"></property>
        <property name="dept" ref="dept"></property>
<!--        <property name="dept.deptName" value="安保部"></property>--> # 必须有get方法
    </bean>
    <bean id="dept" class="com.zwj.bean.Dept" p:deptName="安保部"></bean>
数据、集合、map属性类型注入
    <bean id="stu" class="com.zwj.bean.Stu">
        <!--数组-->
        <property name="courses">
            <array>
                <value>语文</value>
                <value>数学</value>
            </array>
        </property>
        <!--list集合-->
        <property name="list">
            <list>
                <value>1</value>
                <value>2</value>
                <value>3</value>
                <value>4</value>
            </list>
        </property>
        <!--map类型-->
        <property name="map">
            <map>
                <entry key="JAVA" value="java"></entry>
            </map>
        </property>
        <!--list对象类型-->
        <property name="courseList">
            <list>
                <ref bean="course1"></ref>
            </list>
        </property>
    </bean>
    <bean id="course1" class="com.zwj.bean.Course">
        <property name="courseName" value="语文"></property>
    </bean>
    
提取公共集合

引入名称空间util

<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"  # 新增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">
	<bean id="course1" class="com.zwj.bean.Course">
        <property name="courseName" value="语文"></property>
    </bean>
    
    <util:list id="list">
        <ref bean="course1"></ref>
    </util:list>

Bean管理(FactoryBean)

Spring有两种bean
1.普通Bean:在配置文件中定义的class类型就是返回类型
2.工厂Bean(factoryBean):在配置文件中定义的class类型可以和返回类型不一致, 内置bean
1.创建一个类,作为工程bean,实现接口FactoryBean
2.实现接口的方法,实现的方法中定义返回的bean类型
package com.zwj.bean.factory;

import com.zwj.bean.Course;
import org.springframework.beans.factory.FactoryBean;

/**
 * @author zwj
 * @date 2022/2/15 - 13:25
 */
public class MyBean implements FactoryBean {
    //定义返回的bean
    /**
     * 使用getBean()方法时,会返回getObject()中返回的对象,用于配置复杂Bean时,xml配置文件不好配置
     * 接收对象使用getObject()返回的同类型对象
     * */
    
    @Override
    public Object getObject() throws Exception {
        return new Course();
    }

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

<?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 class="com.zwj.bean.factory.MyBean" id="myBean"></bean>

</beans>
//测试工厂bean
    @Test
    public void factoryBean(){
        ApplicationContext context = new ClassPathXmlApplicationContext("factorybean.xml");
        Course myBean = context.getBean("myBean", Course.class);
        System.out.println(myBean);
    }

bean作用域(单例和多例)

1.在spring中,可以设置创建bean实例是单实例还是多实例,默认是单实例对象

使用scope属性设置bean是单例还是多例

# singleton 表示单实例  默认   加载配置文件时会直接创建实例对象
# prototype 表示多实例 		 每次在调用getBean()方法的时候创建一个新的实例对象

<!--多实例-->
    <bean class="com.zwj.bean.Course" id="course" scope="prototype">
        <property name="courseName" value="语文"></property>
    </bean>
//测试单实例和多实例
    @Test
    public void simpleBean(){
    //默认单实例
        ApplicationContext context = new ClassPathXmlApplicationContext("bean-list.xml");
        Stu stu1 = context.getBean("stu", Stu.class);
        Stu stu2 = context.getBean("stu", Stu.class);
        System.out.println(stu1);
        System.out.println(stu2);
    }

bean生命周期

1.通过构造器创建bean实例(无参构造)
2.为bean属性注入值或对其他bean的引用
3.调用bean的初始化方法(需要进行配置)
4.bean可以使用了
5.当容器关闭时,调用bean的销毁的方法(自己配置)
package com.zwj.bean.life;

/**
 * @author zwj
 * @date 2022/2/15 - 13:57
 */
public class Order {

    private String orderName;
    
    public Order() {
        System.out.println("order无参构造被调用......");
    }

    public void setOrderName(String orderName) {
    	System.out.println("set方法被调用......");
        this.orderName = orderName;
    }
    
    //创建初始化执行方法
    public void init(){
        System.out.println("init方法被执行......");
    }
    
    //创建销毁执行方法
    public void destroy(){
        System.out.println("destroy方法被调用.....");
    }
    
}

<?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 class="com.zwj.bean.life.Order" id="order" init-method="init" destroy-method="destroy"></bean>

</beans>
    //测试生命周期
    @Test
    public void lifeTest(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("life.xml");
        context.close();
    }

结果

order无参构造被调用......
set方法被调用......
init方法被执行......
destroy方法被调用.....
后置处理器
1.通过构造器创建bean实例(无参构造)
2.为bean属性注入值或对其他bean的引用
3.把bean实例传递bean后置处理器的方法
4.调用bean的初始化方法(需要进行配置)
5.把bean实例传递bean后置处理器的方法
6.bean可以使用了
7.当容器关闭时,调用bean的销毁的方法(自己配置)
继承BeanPostProcessor接口
# 单独创建一个后置处理器的类
package com.zwj.bean.life;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * @author zwj
 * @date 2022/2/15 - 14:14
 */
public class MyPostProcessor implements BeanPostProcessor {

    //init之前执行的后置处理器
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("init前置处理器被执行.....");
        return bean;
    }

    //init之后执行的后置处理器
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("init后置处理器被执行.....");
        return bean;
    }
}

    <!--创建后置处理器-->
    <bean class="com.zwj.bean.life.MyPostProcessor" id="myPostProcessor"></bean>

xml自动装配

根据指定装配规则(属性名称或属性类型),spring自动将匹配的属性值进行注入
package com.zwj.bean.autowire;

/**
 * @author zwj
 * @date 2022/2/15 - 14:20
 */
public class Emp {

    private Dept dept;

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

    @Override
    public String toString() {
        return "Emp{" +
                "dept=" + dept.toString() +
                '}';
    }
}

package com.zwj.bean.autowire;

/**
 * @author zwj
 * @date 2022/2/15 - 14:20
 */
public class Dept {

    private String deptName;

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

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

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

    <!--自动在spring容器中寻找对应的对象
        byName: 根据属性名称寻找相应名称的对象
        byType: 根据属性类型寻找相应类型的对象
    -->
<!--    <bean class="com.zwj.bean.autowire.Emp" id="emp" autowire="byType"></bean>-->
    <bean class="com.zwj.bean.autowire.Emp" id="emp" autowire="byName"></bean>
    <bean class="com.zwj.bean.autowire.Dept" id="dept">
        <property name="deptName" value="安保部"></property>
    </bean>

</beans>
    //测试自动装配
    @Test
    public void autowire(){
        ApplicationContext context = new ClassPathXmlApplicationContext("autowire.xml");
        Emp emp = context.getBean("emp", Emp.class);
        System.out.println(emp.toString());
    }

外部属性文件

<dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.5</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
    </dependencies>
jdbc.url=jdbc:mysql://localhost:3306/guli?serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.username=root
jdbc.password=root

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!--引入外部配置文件  placeholder 占位符-->
    <context:property-placeholder location="classpath:info.properties"/>

    <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

</beans>

注解创建对象

Spring针对Bean管理中创建对象提供注解
1.@Component
2.@Service
3.@Controller
4.@Repository
Spring自动装配注解
1.@AutoWired 按属性类型装配
2.@Qualifier("") 按属性名称装配,可以指定
3.@Resource(name = "")  默认根据类型进行注入,使用name参数可以设置为名称注入 
4.@Value(value="") 注入普通类型,放在普通属性上

在这里插入图片描述

1.开启组件扫描(告诉spring哪个包中添加了注解)
<!--开启组件扫描-->
    <context:component-scan base-package="com.zwj"/>
package com.zwj.dao;

import org.springframework.stereotype.Repository;

/**
 * @author zwj
 * @date 2022/2/15 - 14:55
 */
@Repository(value = "userDao")
public class UserDao {

    public void add(){
        System.out.println("user add");
    }
}
package com.zwj.controller;

import com.zwj.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 * @author zwj
 * @date 2022/2/15 - 14:57
 */
@Controller
public class UserController {

    @Autowired
    UserDao userDao;

    public void insert(){
        userDao.add();
    }


}

	//测试注解
    @Test
    public void noteTest(){

        ApplicationContext context = new ClassPathXmlApplicationContext("note.xml");
        UserController userController = context.getBean("userController", UserController.class);
        userController.insert();

    }
组件扫描配置
<!-- use-default-filters=false 不使用默认组件扫描 -->
    <context:component-scan base-package="com.zwj" use-default-filters="false">
        <!--不包含某种规则-->
<!--        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>-->
        <!--包含某种规则  与不包含不能同时出现-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值