Spring学习笔记

黑马教学视频链接 https://www.bilibili.com/video/BV1rt4y1u7q5

BeanFactorty版本的快速入门

导入spring坐标

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.7</version>
</dependency>

通过测试类获取Bean(IoC)

test类

package com.tansor.test;

import com.tansor.service.UserService;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;

public class BeanFactoryTest {
    public static void main(String[] args) {
        //创建工厂对象
        DefaultListableBeanFactory beanFactory=new DefaultListableBeanFactory();
        //创建读取器
        XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(beanFactory);
        //读取器配置文件给工厂
        reader.loadBeanDefinitions("beans.xml");
        //根据id获取Bean实例对象
        UserService userService = (UserService) beanFactory.getBean("userService");
        //获取对象信息
        System.out.println(userService);
    }
}

beans.xml

<?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 id="userService" class="com.tansor.service.impl.UserServiceImpl"></bean>
    <!--id为bean识别信息,class为类的路径-->
</beans>

Bean的注入(DI注入)

如下,UserService需要一个UserDao对象,故注入

package com.tansor.service.impl;

import com.tansor.dao.UserDao;
import com.tansor.service.UserService;

public class UserServiceImpl implements UserService {
    public UserDao userDao;
    public void setUserDao(UserDao userDao){
        this.userDao=userDao;
    }

}

beans.xml

<?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 id="userService" class="com.tansor.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"></property><!--将userDao的bean注入-->
        <!--此处name对应userService类中的set方法,如果是方法名称为setUserDao,那么此处userDao,如果是setXyzAbc,那么此处xyzAbc(去掉set首字母大写)-->
        <!--此处ref指的是注入的对象是哪个,写上那个bean的id(此处为userDao)-->
    </bean>

    <bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>

</beans>

ApplicationContext快速入门

IoC

package com.tansor.test;

import com.tansor.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ApplicationContextTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext();
        //ClassPathXmlApplicationContext()直接从resources资源文件夹读取
        //FileSystemXmlApplicationContext()从系统目录路径
        //AnnotationConfigApplicationContext()从注解配置类加载配置文件
        //以上三种只针对基础spring环境
        UserService userService= (UserService) applicationContext.getBean("beans.xml");
    }
}

//BeanFactory直到getBean这一步才会创建Bean
//ApplicationContext加载配置文件后就创建了Bean

基于xml的spring应用

springBean的配置详解

xml配置方式 功能描述
<bean id=""> bean的id和全限定名配置,通过别名也能获取到Bean
<bean name=""> 通过name设置Bean别名,
<bean scope=""> Bean作用范围,BeanFactory作为容器时取值singleton和prototype
<bean lazy-init=""> Bean的实例化时机,是否延迟加载,BeanFactory作为容器时无效
<bean init-method=""> Bean实例化后自动执行的方法,method指定方法名
<bean destory-method=""> Bean实例销毁前的方法
<bean autowire="byType"> 设置自动注入模式,常用的有
1.按照类型——byType
2.按照名字——byName
<bean factory-bean="" factory-method=""/> 指定哪个工厂Bean的哪个方法完成Bean的创建

BeanName

beanName有多种形成方式(绝大多数都只用id,name一辈子也用不到几次,白雪白雪)

  1. 不写id,不写name,beanName为bean中类名的完整引用路径(例如com.tansor.userService.impl.UserServiceImpl)
  2. 写id,不写name,beanName为bean标记中指定的id,此时不允许用完整引用路径去getBean
  3. 写id,写name,beanName为bean标记中指定的id,但是可以通过id或者name去getBean(aliasMap别名映射,将别名映射到id,别名可以写多个,比如id=”aaa,bbb,ccc”)
  4. 不写id,写name,此时beanName从name得到,如果只有一个name那就是name,如果有多个name那就是第一个name作为beanName

Bean的作用范围scope配置

基础spring环境下Bean的作用范围(一般都是singleton)

  1. singleton

    单例,spring容器创建的时候就会进行实例化,存到单例池(一级缓存),每次getBean都是一样的

  2. prototype

    原型,只有getBean时才会创建Bean实例,每次都会创建一个新的实例,不会存进单例池

spring-webmvc

多出来两种scope

  1. request
  2. session

N级缓存是什么

  1. 三级缓存:最底层的缓存,用来存放一个Bean工厂对象,该工厂对象负责生成Bean的代理对象。当检测到循环依赖时,Spring会通过这个工厂对象提前暴露一个Bean的代理对象,以此打破循环依赖singletonFactories
  2. 二级缓存:存放的是提前暴露的、但尚未完全初始化完成的Bean对象(即完成了实例化和部分属性注入,但还未进行初始化方法调用)。这个缓存的存在是为了解决A依赖B,B依赖A这样的场景,在A创建的过程中需要B,而B又依赖于A,这时可以从二级缓存中获取到提前暴露的B的引用,从而解决循环依赖的问题earlySingletonObject
  3. 一级缓存:存放完全初始化好的Bean,单例池singletonObject

Bean延迟加载(对BeanFatory无效)

lazy-init为true时等到你使用getBean才会创建Bean并存储到单例池,否则spring容器一创建就会创建它

init-method

该方法在对象实例化之后执行

destroy-method

必须显式的关闭才会调用,例如applicationContext.close()

InitializingBean

使业务类实现InitializingBean接口,并实现afterPropertiesSet()方法

实例化之后执行属性设置(DI注入),然后执行本方法,然后再执行init-method

Bean有参构造

<?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 id="userService" class="com.tansor.service.impl.UserServiceImpl">
        <constructor-arg name="userDao1" value="userDao"></constructor-arg><!--UserService的构造函数的第一个参数,name是参数名,value对应参数值的bean的id-->
        <constructor-arg name="userDao2" value="userDao"></constructor-arg><!--构造函数的第一个参数,要几个参数创建几个constructor-arg标签-->
        <property name="userDao" ref="userDao"></property>
    </bean>

    <bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>

</beans>

静态工厂

package com.tansor.factory;

import com.tansor.dao.UserDao;
import com.tansor.dao.impl.UserDaoImpl;

public class MyBeanFactory1 {

    public static UserDao userDao(){
        return new UserDaoImpl();
    }

}
<?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 id="userService" class="com.tansor.service.impl.UserServiceImpl">
        <constructor-arg name="userDao1" value="userDao"></constructor-arg>
        <constructor-arg name="userDao2" value="userDao"></constructor-arg>
        <property name="userDao" ref="userDao"></property>
    </bean>

    <bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>

    <bean id="userDao1" class="com.tansor.factory.MyBeanFactory1" factory-method="userDao">
        <!--如果userDao()有参数就增加<constructor-arg>来增加参数-->
    </bean>
    <!--调用MyBeanFactory1中的方法userDao(factory-method),然后把返回的对象实例作为userDao1-->
</beans>

实例工厂(非静态工厂方式)

package com.tansor.factory;

import com.tansor.dao.UserDao;
import com.tansor.dao.impl.UserDaoImpl;

public class MyBeanFactory2 {

    public UserDao userDao(){
        return new UserDaoImpl();
    }

}
<?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 id="userService" class="com.tansor.service.impl.UserServiceImpl">
        <constructor-arg name="userDao1" value="userDao"></constructor-arg>
        <constructor-arg name="userDao2" value="userDao"></constructor-arg>
        <property name="userDao" ref="userDao"></property>
    </bean>

    <bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>

    <bean id="beanFactory2" class="com.tansor.factory.MyBeanFactory2"></bean>
    <!--实例化一个bean-->
    <bean id="userDao2" factory-bean="beanFactory2" factory-method="userDao">
        <!--如果userDao()有参数就增加<constructor-arg>来增加参数-->
    </bean>
    <!--用刚才实例化的bean作为factory-bean,调用其中的userDao(),获取返回的UserDao作为MyBeanFactory2-->
</beans>

实现FactoryBean规范延迟Bean实例化

package com.tansor.factory;

import com.tansor.dao.UserDao;
import com.tansor.dao.impl.UserDaoImpl;
import org.springframework.beans.factory.FactoryBean;

public class MyBeanFactory3 implements FactoryBean<UserDao> {
    //继承FactoryBean
    @Override
    public UserDao getObject() throws Exception {
        return new UserDaoImpl();
    }

    @Override
    public Class<?> getObjectType() {
        return UserDao.class;
    }
}
<?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 id="userService" class="com.tansor.service.impl.UserServiceImpl">
        <constructor-arg name="userDao1" value="userDao"></constructor-arg>
        <constructor-arg name="userDao2" value="userDao"></constructor-arg>
        <property name="userDao" ref="userDao"></property>
    </bean>

    <bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>

    <bean id="userDao3" class="com.tansor.factory.MyBeanFactory3"></bean>
    <!--返回的是MyBeanFactory3使用getObject()返回的对象实例-->
    <!--单例池中userDao3对应的其实是MyBeanFactory3,只有当测试类中getBean被执行时,才会生成真正的返回的对象userDao3存储在factoryBeanObjectCache中-->
</beans>

注入方式和注入数据类型(手动装配)

通过set方法注入

  • 普通数据类型

​ 例如String ,int,boolean等

<?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 id="userService" class="com.tansor.service.impl.UserServiceImpl">
        <property name="userName" ref="xiaoming"></property><!--普通属性值注入使用value,此时UserServiceImpl中有方法setUserName()-->
    </bean>

    <bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>

</beans>
  • 引用数据类型
<?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 id="userService" class="com.tansor.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"></property><!--引用注入使用ref,此时UserServiceImpl中有方法setUserDao()-->
    </bean>

    <bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>

</beans>
  • 集合数据类型
<?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 id="userService" class="com.tansor.service.impl.UserServiceImpl">
        <property name="stringList">
            <list><!--是List类型写List,是Set就写Set,是-->
                <value>aaa</value><!--普通属性值直接往里写-->
                <value>bbb</value>
                <value>ccc</value>
            </list>
        </property>
        <property name="userDaoList">
            <list>
                <ref bean="userDao1"></ref><!--引用外面的bean-->
                <ref bean="userDao2"></ref>
                <bean class="com.tansor.dao.impl.UserDaoImpl"></bean><!--也可以直接配一些bean-->
            </list>
        </property>
        <property name="userDaoMap">
            <map>
                <entry key="key1" value="value1"></entry><!--普通类型的变量注入直接key-value-->
                <entry key="key1" value-ref="userDao1"></entry><!--引用对象实例的变量注入直接key-value-ref-->
            </map>
        </property>
        <property name="userDaoMap">
            <props><!--Properties类型的注入-->
                <prop key="prop1">value1在此</prop>
                <prop key="prop2">value2在此</prop>
            </props>
        </property>
    </bean>

    <bean id="userDao1" class="com.tansor.dao.impl.UserDaoImpl"></bean>

    <bean id="userDao2" class="com.tansor.dao.impl.UserDaoImpl"></bean>

</beans>

通过构造方法注入

<property name="userName" ref="xiaoming"></property>中的 property 换成 constructor-arg

自动装配

根据name自动装配

<?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 id="userService" class="com.tansor.service.impl.UserServiceImpl" autowire="byName"></bean>
    <!--autowire为byName时,会自动检测UserServiceImpl中的set函数,去掉set首字母大写,并在寻找id与这个相同的bean进行导入-->

</beans>

根据type进行自动装配

<?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 id="userService" class="com.tansor.service.impl.UserServiceImpl" autowire="byType"></bean>
    <!--autowire为byName时,会自动检测UserServiceImpl中的set函数中参数的类型,并在寻找类型与这个相同的bean进行导入,如果相同类型bean数量对不上参数表中数量编译器就会报错-->

    <bean id="userDao1" class="com.tansor.dao.impl.UserDaoImpl"></bean>

    <bean id="userDao2" class="com.tansor.dao.impl.UserDaoImpl"></bean>

</beans>

黑马《黑马程序员新版Spring零基础入门到精通,一套搞定spring全套视频教程(含实战源码)》P26-P30不看了太麻烦了

getBean三种API

方法定义 返回的值和参数
Object getBean(String beanName) 返回为Object,需要强行转换类型
T getBean(Class Type) 当beans中这种类型的bean只存在一个时可以用,否则不行
T getBean(String beanName,Class type) 肥肠好,指定classtype使用UserService.class

Spring导入非自定义Bean

现在Maven导入jdbc和alibaba数据源坐标

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>spring_test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.7</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.23</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
    </dependencies>

</project>

bean配置文件中导入

<?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 id="userService" class="com.tansor.service.impl.UserServiceImpl" autowire="byName"></bean>

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

</beans>

导入mysql的Connection

<?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 id="userService" class="com.tansor.service.impl.UserServiceImpl" autowire="byName"></bean>

    <bean id="aClass" class="java.lang.Class" factory-method="forName">
        <constructor-arg name="className" value="com.mysql.jdbc.Driver"></constructor-arg>
    </bean>

    <bean id="connection" class="java.sql.DriverManager" factory-method="getConnection">
        <constructor-arg name="url" value="com.mysql.jdbc.Driver"></constructor-arg>
        <constructor-arg name="user" value="root"></constructor-arg>
        <constructor-arg name="password" value="root"></constructor-arg>
    </bean>
    <!--对应以下语句
        Class.forName("com.mysql.jdbc.Driver");
        Connection connection= DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis_db","root","root");
    -->

</beans>

时间转化为标准格式并获取Date对象

<?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 id="userService" class="com.tansor.service.impl.UserServiceImpl" autowire="byName"></bean>

    <bean id="simpleDateFormat" class="java.text.SimpleDateFormat" scope="prototype">
        <constructor-arg name="pattern" value="yyyy-MM-dd HH:mm:ss"></constructor-arg>
    </bean>
    <!--对应SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");-->

    <bean id="date" factory-bean="simpleDateFormat" factory-method="parse">
        <constructor-arg name="source" value="2024-03-08 21:56:00"></constructor-arg>
    </bean>
    <!--对应Date date=simpleDateFormat.parse(currentTimeStr);-->

</beans>
package com.tansor.test;

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

public class ApplicationContextTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        System.out.println(applicationContext.getBean("date"));
    }
}

配置sqlSessionFactory(MyBatis)

导入maven坐标

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.5</version>
</dependency>

在resource目录下新建mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
    </mappers>
</configuration>
传统做法

测试类

package com.tansor.test;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

public class ApplicationContextTest {
    public static void main(String[] args) throws Exception {
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory=builder.build(in);
    }
}
白雪做法(配个Bean)
<?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 id="userService" class="com.tansor.service.impl.UserServiceImpl" autowire="byName"></bean>

<!--    InputStream in = Resources.getResourceAsStream("mybatis-config.xml");-->
<!--    SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();-->
<!--    SqlSessionFactory sqlSessionFactory=builder.build(in);-->

    <bean id="inputStream" class="org.apache.ibatis.io.Resources" factory-method="getResourceAsStream">
        <constructor-arg name="resource" value="mybatis-config.xml"></constructor-arg>
    </bean>

    <bean id="builder" class="org.apache.ibatis.session.SqlSessionFactoryBuilder"></bean>

    <bean id="sessionFactory" factory-bean="builder" factory-method="build">
        <constructor-arg name="inputStream" ref="inputStream"></constructor-arg><!--注意此处ref-->
    </bean>

</beans>

BeanDefinition(Bean的实例化基本流程)

Spring容器在进行初始化时,一个Bean信息存储到一个BeanDefinition对象中,很多的BeanDefinition对象都存储在beanDefinitionMap集合(位于BeanFactory中)中,Spring框架在对该Map进行遍历,使用反射创建Bean实例对象,创建好的Bean对象存储在一个名为singletonObjects的Map集合中,当调用getBean方法时则最终从该Map集合中取出Bean实例对象返回。

BeanDefinitionMap中存的不是Bean的对象,存的仅仅是Bean的配置

image-20240308234055822

image-20240308234113041

image-20240308234131330

image-20240308234147166

image-20240308234200279

image-20240308234216226

Bean工厂后处理器BeanFactoryProcessor

新建一个类MyBeanFactoryPostProcessor实现接口BeanFactoryPostProcessor,并实现方法postProcessBeanFactory,此方法中的参数(configurableListableBeanFactory)存储的就是BeanDefinitionMap,通过一下手段可以修改某些Bean的配置参数

package com.tansor.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("BeanDefinitionMap完毕后自动回调此方法");
        // 获取名为userDao的Bean
        BeanDefinition userDao = configurableListableBeanFactory.getBeanDefinition("userDao");
        // 将这个Bean的类名改为UserServiceImpl,实现偷天换日
        userDao.setBeanClassName("com.tansor.service.impl.UserServiceImpl");
    }
}

image-20240309144319752

bean配置文件如下

<?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.tansor.processor.MyBeanFactoryPostProcessor"></bean>

    <bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>

    <bean id="userService" class="com.tansor.service.impl.UserServiceImpl"></bean>
</beans>

动态注册BeanDefinition(没用,白雪)

第一种,向上转型进行注册

package com.tansor.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("BeanDefinitionMap完毕后自动回调此方法");
        BeanDefinition beanDefinition=new RootBeanDefinition();//创建一个新的BeanDefinition对象
        beanDefinition.setBeanClassName("com.tansor.dao.impl.PersonDaoImpl");//设置Bean的参数配置
        DefaultListableBeanFactory defaultListableBeanFactory=(DefaultListableBeanFactory) configurableListableBeanFactory;//将参数向上转型,以获得更多API
        defaultListableBeanFactory.registerBeanDefinition("personDao",beanDefinition);//注册新的Bean
    }
}
package com.tansor.test;

import com.tansor.dao.PersonDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ApplicationContextTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("ApplicationContext.xml");
        Object userDao = applicationContext.getBean(PersonDao.class);
        System.out.println(userDao);
    }

}
<?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.tansor.processor.MyBeanFactoryPostProcessor"></bean>
    <!--后处理器配置在配置文件-->

    <bean id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>

    <bean id="userService" class="com.tansor.service.impl.UserServiceImpl"></bean>
</beans>

第二种,实现子接口进行注册

新建一个类MyBeanDefinitionRegisterPostProcessor实现接口BeanDefinitionRegistryPostProcessor,并实现方法注册方法

package com.tansor.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;

public class MyBeanDefinitionRegisterPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        BeanDefinition beanDefinition=new RootBeanDefinition();
        beanDefinition.setBeanClassName("com.tansor.dao.impl.PersonDaoImpl");
        beanDefinitionRegistry.registerBeanDefinition("personDao",beanDefinition);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}
<?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 id="userDao" class="com.tansor.dao.impl.UserDaoImpl"></bean>

    <bean id="userService" class="com.tansor.service.impl.UserServiceImpl"></bean>

    <bean class="com.tansor.processor.MyBeanDefinitionRegisterPostProcessor"></bean>
    <!--后处理器配置在配置文件-->
</beans>

加载properties文件

<?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/beans/spring-context.xsd
    ">
    <!--开启context命名空间 ^ -->

    <!--使用context空间加载properties文件-->
    <context:property-placeholder location="jdbc.properties" />

    <!--使用属性占位符${}获取文件内容-->
    <bean class="com.alibaba.druid.pool.DruidDataSource">
        <property name="name" 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>

注解自动扫描

package com.tansor.dao.impl;

import com.tansor.dao.UserDao;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

@Controller//表现层
@Component
@Service//业务层
@Repository//数据层
public class UserDaoImpl implements UserDao {
}
<?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.tansor" />
    <!--注解扫描范围定义,可以同时扫多个包-->

</beans>

纯注解开发模式

新建一个类SpringConfig

package com.tansor.config;

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

@Configuration
@ComponentScan({"com.tansor","com.tansor2"})//可以写好几个,写好几个需要在外面加{}
public class SpringConfig {
}
import com.tansor.config.SpringConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
//加载注解类配置
public class AppForAnnotation {
    ApplicationContext ctx=new AnnotationConfigApplicationContext(SpringConfig.class);
}

注解开发模式下bean生命周期

设置单例模式
package com.tansor.dao.impl;

import com.tansor.dao.UserDao;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;

@Repository
@Scope("singleton")//单例
public class UserDaoImpl implements UserDao {

}
设置原型模式
package com.tansor.dao.impl;

import com.tansor.dao.UserDao;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Repository
@Scope("prototype")//原型模式
public class UserDaoImpl implements UserDao {

    @PostConstruct
    public void init(){
        System.out.println("初始化后执行");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("销毁前执行");
    }
}

纯注解开发依赖注入(自动装配)

package com.tansor.dao.impl;

import com.tansor.dao.UserDao;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Repository("userDao")  //指定bean的name
@Scope("prototype")
public class UserDaoImpl implements UserDao {

    @PostConstruct
    public void init(){
        System.out.println("初始化后");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("销毁前");
    }
}
package com.tansor.service.impl;

import com.tansor.dao.UserDao;
import com.tansor.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class UserServiceImpl implements UserService {
    @Autowired  //自动装配
    @Qualifier("userDao")   //加载指定name的bean
    private UserDao userDao;//无需setter方法,暴力反射注入
}
简单类型的注入
package com.tansor.service.impl;

import com.tansor.dao.UserDao;
import com.tansor.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class UserServiceImpl implements UserService {
    @Value("testValue")//简单类型注入
    private String test;
}
简单类型注入(加载properties文件)
使用配置类载入properties文件
package com.tansor.config;

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

@Configuration
@ComponentScan("com.tansor")
@PropertySource({"jdbc.properties"})    //载入properties文件
public class SpringConfig {
}
在业务类中使用${jdbc.url}引用properties文件中的参数
package com.tansor.service.impl;

import com.tansor.dao.UserDao;
import com.tansor.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class UserServiceImpl implements UserService {
    @Value("${jdbc.url}")
    public String url;
}

注解开发管理第三方Bean

导入DruidDataSource数据源

集中在SpringConfig管理

package com.tansor.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
public class SpringConfig {

    //1.定义一个方法获得要管理的对象
    //2.添加@Bean,表示当前返回值是个Bean
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds=new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }

}
/*
测试类
*/
import com.tansor.config.SpringConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import javax.sql.DataSource;

public class AppForAnnotation {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext(SpringConfig.class);
        DataSource dataSource=ctx.getBean(DataSource.class);
        System.out.println(dataSource);
    }
}

分散到各个Config类

定义JdbcConfig.java专门用于JDBC配置操作
package com.tansor.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;

public class JdbcConfig {
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds=new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring");
        ds.setUsername("root");
        ds.setPassword("root");
        return ds;
    }
}
在SpringConfig.java导入JDBC配置文件
package com.tansor.config;

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

@Configuration
@Import({JdbcConfig.class}) //可以写多个
public class SpringConfig {

}

为第三方Bean注入依赖

第三方Bean简单类型注入

package com.tansor.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;

public class JdbcConfig {
    @Value("com.mysql.jdbc.Driver")
    private String driver;
    @Value("jdbc:mysql://localhost:3306/spring")
    private String url;
    @Value("root")
    private String userName;
    @Value("root")
    private String password;

    @Bean
    public DataSource dataSource(){
        DruidDataSource ds=new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

引入properties也可以,参考之前的jdbc.url那种参数引入(${jdbc.url})

第三方Bean引用类型注入

先在总Config类扫自动装配

package com.tansor.config;

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

@Configuration
@Import(JdbcConfig.class)
@ComponentScan("com.tansor")
public class SpringConfig {

}
package com.tansor.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.tansor.dao.UserDao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;

public class JdbcConfig {
    @Value("com.mysql.jdbc.Driver")
    private String driver;
    @Value("jdbc:mysql://localhost:3306/spring")
    private String url;
    @Value("root")
    private String userName;
    @Value("root")
    private String password;

    @Bean
    public DataSource dataSource(UserDao userDao){//此处按类型自动装配
        System.out.println(userDao);
        DruidDataSource ds=new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇