spring6入门之ioc-基于xml方式注入

jdk使用17的版本

pom.xml 

    <!--这里必须要加 否则会报版本错误-->
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
      
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.8.2</version>
        </dependency>

    </dependencies>

控制反转(ioc):就是把new对象,交给spring来去new;

依赖注入(di): 就是对控制反转的具体实现

所谓的注入,就是给字段赋值

bean.xml就是对应BeanDefinition,叫做bean定义信息

要想读取这些bean.xml文件的内容就需要一个接口,就是BeanDefinitionReader

然后把这些bean交友ioc来管理

然后解析这些配置

可以通过BeanFactory+反射的方式来实例化(就是new对象)

实例化完,还不能直接使用这个对象,还需要进行初始化

就是set属性赋值

然后你在从上下文中去获取bean就有数据了

我们先来看下set注入

创建bean.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">

    <!--id 随便定义,class 类路径  要在context.getBean("这里匹配上") -->
    <bean id="a" class="com.dmg.A">
        <!--属性 字段 值-->
        <property name="name" value="张三"></property>
    </bean>
</beans>

package com.dmg;

public class A {

    private String name;

    public A(){
        System.out.println("无参构造A");
    }

    public void setName(String name) {
        System.out.println("set注入");
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

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

public class B {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");

        A a=(A)context.getBean("a");
        System.out.println(a);
        a.add();


    }
}

 我们在来看下有参方法构造注入

对A类进行改造

   public A(String name){
        System.out.println("我是有参构造A");
        this.name=name;
    }

修改bean.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">

    <!--id 随便定义,class 类路径  要在context.getBean("这里匹配上") -->
    <bean id="a" class="com.dmg.A">
        <!--有参构造注入 字段  值-->
        <constructor-arg name="name" value="李四"></constructor-arg>
    </bean>
</beans>

 接下来我们在看下引用其他对象

package com.dmg;

public class A {

    private String name;

    private C cc;

    public A(){
        System.out.println("无参构造A");
    }

    public String getName() {
        return name;
    }

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

    public C getCc() {
        return cc;
    }

    public void setCc(C cc) {
        this.cc = cc;
    }

    @Override
    public String toString() {
        return "A{" +
                "name='" + name + '\'' +
                ", cc=" + cc +
                '}';
    }
}
package com.dmg;

public class C {

    private Integer age;

    public C(){
        System.out.println("无参构造c");
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "C{" +
                "age=" + age +
                '}';
    }
}

bean.xml中使用ref引用其他的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">

    <!--id 随便定义,class 类路径  要在context.getBean("这里匹配上") -->
    <bean id="a" class="com.dmg.A">
       <property name="name" value="张三"></property>
       <property name="cc" ref="c"></property>
    </bean>

    <bean id="c" class="com.dmg.C">
        <property name="age" value="18"></property>
    </bean>


</beans>

接下来我们在来看下map注入 

package com.dmg;

import java.util.Map;

public class A {

    private String name;

    private Map<String,C> map;

    public String getName() {
        return name;
    }

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

    public Map<String, C> getMap() {
        return map;
    }

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

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

修改bean.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">

    <!--id 随便定义,class 类路径  要在context.getBean("这里匹配上") -->
    <bean id="a" class="com.dmg.A">
       <property name="name" value="张三"></property>
        <property name="map" >
            <map>
                <entry>
                    <key>
                        <value>1111</value>
                    </key>
                    <ref bean="c"></ref>
                </entry>
                <entry>
                    <key>
                        <value>2222</value>
                    </key>
                    <ref bean="c"></ref>
                </entry>
            </map>

        </property>
    </bean>

    <bean id="c" class="com.dmg.C">
        <property name="age" value="18"></property>
    </bean>


</beans>

接下来我们在来看下list注入

package com.dmg;

import java.util.List;
import java.util.Map;

public class A {

    private String name;

    private List<C> list;

    public String getName() {
        return name;
    }

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

    public List<C> getList() {
        return list;
    }

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

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

修改bean.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">

    <!--id 随便定义,class 类路径  要在context.getBean("这里匹配上") -->
    <bean id="a" class="com.dmg.A">
       <property name="name" value="张三"></property>
        <property name="list">
            <list>
                <ref bean="c"></ref>
                <ref bean="c"></ref>
            </list>
        </property>
    </bean>

    <bean id="c" class="com.dmg.C">
        <property name="age" value="18"></property>
    </bean>


</beans>

接下来我们在看下数组注入

package com.dmg;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class A {

    private String name;

    private String[]sz;

    public String getName() {
        return name;
    }

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

    public String[] getSz() {
        return sz;
    }

    public void setSz(String[] sz) {
        this.sz = sz;
    }

    @Override
    public String toString() {
        return "A{" +
                "name='" + name + '\'' +
                ", sz=" + Arrays.toString(sz) +
                '}';
    }
}

修改bean.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">

    <!--id 随便定义,class 类路径  要在context.getBean("这里匹配上") -->
    <bean id="a" class="com.dmg.A">
       <property name="name" value="张三"></property>
        <property name="sz">
            <array>
               <value>1121</value>
               <value>222</value>
            </array>
        </property>
    </bean>




</beans>

接下来我们在来看下util标签注入

修改bean.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"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd"

>

    <!--id 随便定义,class 类路径  要在context.getBean("这里匹配上") -->
    <bean id="a" class="com.dmg.A">
       <property name="name" value="张三"></property>
       <property name="list">
           <util:list >
               <ref bean="c"></ref>
               <ref bean="c"></ref>
           </util:list>
       </property>
    </bean>


    <bean id="c" class="com.dmg.C">
        <property name="age" value="222"></property>
    </bean>

</beans>

接下来我们在看下来p标签 简写注入

修改bean.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"
       xmlns:util="http://www.springframework.org/schema/util"
       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
       http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd"

>

    <!--id 随便定义,class 类路径  要在context.getBean("这里匹配上") -->
    <bean id="a" class="com.dmg.A" p:name="张三" p:list-ref="list1">
    </bean>

    <util:list id="list1">
        <ref bean="c"></ref>
        <ref bean="c"></ref>
    </util:list>


    <bean id="c" class="com.dmg.C">
        <property name="age" value="222"></property>
    </bean>

</beans>

接下来我们看下引入外部属性文件

先在pom.xml加入

  <!-- MySQL驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>
        <!-- 数据源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.15</version>
        </dependency>

创建jdbc.properties文件

jdbc.user=root
jdbc.password=123456
jdbc.url=jdbc:mysql://localhost:3306/dmg?serverTimezone=UTC
jdbc.driver=com.mysql.cj.jdbc.Driver

修改bean.xml文件,使用context标签引入外部文件

<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/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--外部文件路径-->
    <context:property-placeholder location="jdbc.properties"></context:property-placeholder>
    <!--引入外部文件 通过占位符赋值-->
   <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc.user}"></property>
       <property name="password" value="${jdbc.password}"></property>
       <property name="url" value="${jdbc.url}"></property>
       <property name="driverClassName" value="${jdbc.driver}"></property>
   </bean>

</beans>

然后我们就能动态的修改外部的配置文件了

public class B {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");

        DruidDataSource druidDataSource=(DruidDataSource)context.getBean("druidDataSource");
        System.out.println(druidDataSource.getUrl());
        System.out.println(druidDataSource.getPassword());

    }
}

接下来我们在来看下bean的作用域

pom.xml加入日志

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.13.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.13.3</version>
        </dependency>

创建log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <loggers>
        <!--
            level指定日志级别,从低到高的优先级:
                TRACE < DEBUG < INFO < WARN < ERROR < FATAL
                trace:追踪,是最低的日志级别,相当于追踪程序的执行
                debug:调试,一般在开发中,都将其设置为最低的日志级别
                info:信息,输出重要的信息,使用较多
                warn:警告,输出警告的信息
                error:错误,输出错误信息
                fatal:严重错误
        -->
        <root level="DEBUG">
            <appender-ref ref="spring6log"/>
            <appender-ref ref="RollingFile"/>
            <appender-ref ref="log"/>
        </root>
    </loggers>

    <appenders>
        <!--输出日志信息到控制台-->
        <console name="spring6log" target="SYSTEM_OUT">
            <!--控制日志输出的格式-->
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss SSS} [%t] %-3level %logger{1024} - %msg%n"/>
        </console>

        <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用-->
        <File name="log" fileName="d:/spring6_log/test.log" append="false">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
        </File>

        <!-- 这个会打印出所有的信息,
            每次大小超过size,
            则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,
            作为存档-->
        <RollingFile name="RollingFile" fileName="d:/spring6_log/app.log"
                     filePattern="log/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
            <PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>
            <SizeBasedTriggeringPolicy size="50MB"/>
            <!-- DefaultRolloverStrategy属性如不设置,
            则默认为最多同一文件夹下7个文件,这里设置了20 -->
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>
    </appenders>
</configuration>
public class A {


}

bean.xml 使用scope="singleton" 或者不写表示单例

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

   <bean id="a" class="com.dmg.A" scope="singleton">

   </bean>
</beans>

 我们可以看到在初始化的时候才创建单实例bean,在获取的时候不会创建

2个对象的地址都是一样的,这就是单实例

 在bean.xml中改成多实例,scope="prototype"

可以看到2个对象的地址都不一样了

接下来我们来看下bean的生命周期


bean对象创建(调用无参构造器)
给bean对象设置属性
bean的后置处理器(初始化之前)
bean对象初始化(需要在配置bean时指定初始化方法)
bean的后置处理器(初始化之后)
bean对象就绪可以使用
bean对象销毁(需要在配置bean时指定销毁方法)
ioc容器关闭


public class A {


    public A(){
        System.out.println("1:无参构造");
    }
    private String name;

    public void setName(String name) {
        System.out.println("2:属性赋值");
        this.name = name;
    }


    public void init(){
        System.out.println("4:初始化");
    }

    public void xiaoHui(){
        System.out.println("6:销毁");
    }
}

创建自定义的bean后置处理器,这个后置处理器针对的是所有的ioc容器中的bean


/**
 * 自定义后置处理器
 */
public class C implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("3:初始化之前: "+beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("5:初始化之后:"+beanName);
        return bean;
    }
}

public class B {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");

        A a=(A)context.getBean("a");
        //销毁
        context.close();
    }
}

创建bean.xml

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

   <bean id="a" class="com.dmg.A" init-method="init" destroy-method="xiaoHui">
        <property name="name" value="张三"></property>
   </bean>

   <bean id="c" class="com.dmg.C"></bean>
</beans>

生命周期总结:实例化(创建对象)->属性赋值->初始化->销毁 

接下来我们在来看下工厂bean(FactoryBean),

就是可以创建对象,通过&前缀来返回不同的类

/**
 * 自定义工厂bean
 */
public class MyFactoryBean implements FactoryBean<A> {


    //创建对象
    @Override
    public A getObject() throws Exception {
        return new A();
    }

    //返回对象类型
    @Override
    public Class<?> getObjectType() {
        return A.class;
    }
}

修改bean.xml

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


   <bean id="c" class="com.dmg.C"></bean>

    <bean id="myFactoryBean" class="com.dmg.MyFactoryBean"></bean>


</beans>
public class B {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");

        //加&前缀 返回的就是MyFactoryBean
        System.out.println(context.getBean("&myFactoryBean"));
        //不加前缀 返回的就是A 就是泛型中的类
        System.out.println(context.getBean("myFactoryBean"));
    }
}

接下来我们在来看下bean的自动装配 

自动装配:根据指定的策略 在ioc容器中匹配某一个bean自动为指定的bean中所依赖的类类型或者接口类型 属性赋值

我们先来看下类型注入

public class MyController {

    private MyService myService;

    public void setMyService(MyService myService) {
        System.out.println("set注入");
        this.myService = myService;
    }

    public void add(){
        System.out.println("控制层");
        myService.add();
    }

}
public interface MyService {

    public void add();
}
public class MyServiceImpl implements MyService{

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

修改bean.xml,使用 autowire="byType"就是根据类型注入

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



   <bean id="myController" class="com.dmg.MyController" autowire="byType">

   </bean>
    <bean id="myServiceImpl" class="com.dmg.MyServiceImpl">

    </bean>



</beans>
public class B {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");
        MyController myController=(MyController)context.getBean("myController");
        myController.add();
    }
}

 接下来我们在来看下根据名称注入,改成

autowire="byName"

可以看到报错了,为啥呢?

 因为和要这里的myService的名字一样

 这次就可以了

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值