spring的IOC控制反转

1.IOC控制反转

 

IOC:(Inversion(反转) Of Control):控制反转;

控制:资源的获取方式;

主动式:(要什么资源都自己创建即可)

BookServlet{                  
        //自己new对象
         BookService bs = new BookService();   
        AirPlane ap = new AirPlane();//复杂对象的创建是比较庞大的工程                }     

 

被动式:资源的获取不是我们自己创建,而是交给一个容器来创建和设置;               
            BookServlet{    
                BookService bs;
                public void test01(){
                    bs.checkout();
                }           
            }

 

容器:管理所有的组件(有功能的类);假设,BookServlet受容器管理,BookService也受容器管理;容器可以自动的探查出那些组件(类)需要用到另一写组件(类);容器帮我们创建BookService对象,并把BookService对象赋值过去; 容器:主动的new资源变为被动的接受资源;

ioc解释

IOC(容器)婚介所: 主动获取变为被动接受; DI:(Dependency Injection)依赖注入: 容器能知道哪个组件(类)运行的时候,需要另外一个类(组件);容器通过反射的形式,将容器中准备好的BookService对象注入(利用反射给属性赋值)到BookServlet中;

只要IOC容器管理的组件,都能使用容器提供的强大功能; HelloWorld;

(通过各种方式给容器中注册对象(注册会员))

以前是自己new 对象,现在所有的对象交给容器创建;给容器中注册组件

1.1getBean的使用

//       getBean()获取xml中配置的id(唯一标识)
        User user = (User) applicationcontext.getBean("user");
//        方式二根据反射获取 但是只能当只创建一个对象时候有用
      //  User bean = applicationcontext.getBean(User.class);
//        方式三 根据xml的唯一标识id获取后面加类 (这样就不要类型强转了)
        User user1 = applicationcontext.getBean("user", User.class);
//        获取有参构造赋值
        User user2 = applicationcontext.getBean("user2", User.class);
//      System.out.println(bean);
        System.out.println(user2);
        System.out.println(user);
        System.out.println(user1);

1.2spring配置有参无参构造方法

<?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注册对象 = new对象这里交给容器了
                class表示类
                id对象名(唯一)
​
    -->
    <bean class="com.tc.bean.User" id="user">
        <!--
            使用property标签为User对象的属性赋值
            name="lastName":指定属性名
            value="张三":为这个属性赋值
            name值是由setter赋值的
        -->
        <!--        property是通过调用无参 使用getter赋值-->
        <property name="id" value="01"/>
        <property name="name" value="谭铖"/>
        <property name="sex" value="男"/>
        <property name="email" value="男"/>
    </bean>
​
    <bean class="com.tc.bean.User" id="user2">
<!--
          有参构造方法赋值
-->
        <constructor-arg name="id" value="2"/>
        <constructor-arg name="email" value="email"/>
        <constructor-arg name="sex" value="男"/>
        <constructor-arg name="name" value="李母猪"/>
    </bean>
<!--    有参构造方法的多种赋值方式-->
    <bean class="com.tc.bean.User" id="user3">
<!--    public User(Integer id, String name, String sex, String email) {-->
<!--        根据value赋值的话必须按照构造方法赋值-->
        <constructor-arg value="3"/>
        <constructor-arg value="java"/>
        <constructor-arg value="女"/>
        <constructor-arg value="qq.com"/>
    </bean>
    <bean class="com.tc.bean.User" id="user4">
<!--        当顺序不一致可以用index赋值从开始排序赋值-->
        <constructor-arg value="3" index="0"/>
        <constructor-arg value="tancheng" index="1"/>
        <constructor-arg value="qq.com1" index="3"/>
        <constructor-arg value="男" index="2"/>
    </bean>
<bean class="com.tc.bean.User" id="user5">
<!--    当有多个有参构造方法的重载的时候 可以利用type写全属性进行赋值-->
<!--    public User( String name, String email,Integer id) {-->
<!--    public User(Integer id, String name, String sex) {-->
    <constructor-arg value="tancheng" type="java.lang.String"/>
    <constructor-arg value="qq.eam" type="java.lang.String"/>
    <constructor-arg value="01" type="java.lang.Integer"/>
</bean>
</beans>

 

1.3Spring使用p名称空间配置属性

更加方便

<!--    使用p标签配置命名空间 -->
    <bean class="com.tc.bean.User" id="user6"
          p:id="22" p:name="tanchengggg"p:email="ewew@qq.cpm" p:sex="nan">
<!--        通过p:标签命名 要导入xmlns:p="http://www.springframework.org/schema/p"就可以使用了-->
    </bean>

1.4类中类使用

bean写全局的可以随处获取

局部的不行局部就不要写id了写了等于没有写呢亲

<!--    传类的对象赋值方法一-->
<!--    首先创建好一个Cat类-->
    <bean class="com.tc.bean.Cat" id="cat2">
        <property name="name" value="奥迪"/>
        <property name="price" value="100000"/>
    </bean>
<!--    使用ref直接引用-->
<!-- ref:代表引用外面的一个值 ;引用其他bean car = ioc.getBean("car01") -->
    <bean class="com.tc.bean.User" id="user8">
        <property name="cats" ref="cat2"/>
    </bean>
<!--    传类的对象赋值方法二-->
    <bean class="com.tc.bean.User" id="user7">
<!--        获取setter方法 套一个bean再赋值-->
        <property name="cats">
 <!--对象我们可以使用bean标签创建 car = new Car(); 引用内部bean;不能被获取到,只能内部使用 -->
            <bean class="com.tc.bean.Cat" id="cat1">
                <property name="name" value="宝马"/>
                <property name="price" value="10000"/>
            </bean>
        </property>
    </bean>

1.5List集合的赋值

<!--List对象的使用-->
    <bean class="com.tc.bean.User" id="user9">
        <property name="catList">
<!-- 相当于cats = new ArrayList<Cat>(); -->
           <list>
               <!-- list标签体中添加每一个元素 -->
               <bean class="com.tc.bean.Cat">
                   <property name="name" value="保时捷"/>
                   <property name="price" value="22222"/>
               </bean>
<!--               引用外部元素 不能引用别的地方内部bean-->
               <ref bean="cat2"/>
           </list>
        </property>
    </bean>

1.6map集合的赋值/Properties对象的使用

<!--    map对象的使用-->
<bean class="com.tc.bean.Cat" id="cat01">
    <property name="name" value="西游记"/>
</bean>
    <bean class="com.tc.bean.User" id="user10">
        <property name="map">
<!--            相当于创建了map-->
            <map>
                <!--赋值-->
                <entry key="01" value="111"/>
<!--                外部bean赋值-->
                <entry key="02" value-ref="cat01"/>
<!--                内部bean赋值-->
                <entry key="03">
                    <bean class="com.tc.bean.Cat">
                        <property name="name" value="洗衣液"/>
                        <property name="price" value="122"/>
                    </bean>
                </entry>
<!--                value传参-->
                <entry key="05">
                    <value>哈哈哈哈</value>
                </entry>
<!--                套娃 嵌套一个map-->
                <entry key="06">
                    <map>
                        <entry key="01" value="222"/>
                    </map>
                </entry>
            </map>
        </property>
<!--        Properties对象的使用-->
        <property name="properties">
            <!-- properties = new Properties();所有的k=v都是string -->
            <props >
                <!-- k=v都是string;值直接写在标签体中 -->
                <prop key="username">root</prop>
                <prop key="password">1234</prop>
            </props>
        </property>
    </bean>

1..6util的使用

 <!-- util名称空间创建集合类型的bean;方便别人引用 -->
<!--    需要引入 xmlns:util="http://www.springframework.org/schema/util"-->
    <bean class="com.tc.bean.User" id="user11">
        <property name="map" ref="mapUtil"/>
        <property name="catList" ref="listUtil"/>
        <property name="properties" ref="propertiesUtil"/>
        <property name="sets" ref="setUtil"/>
    </bean>
        <!--            相当于创建了map 必须设置id-->
        <util:map id="mapUtil">
            <entry key="01" value="tancheng"/>
<!--            引用外部bean-->
            <entry key="02" value-ref="cat01"/>
<!--           内部bean-->
            <entry key="03">
                <bean class="com.tc.bean.Cat">
                    <property name="name" value="asd"/>
                    <property name="price" value="22"/>
                </bean>
            </entry>
<!--                value传参-->
            <entry key="05">
                <value>哈哈哈哈</value>
            </entry>
 <!--                套娃 嵌套一个map-->
            <entry key="06">
                <map>
                    <entry key="01" value="222"/>
                </map>
            </entry>
        </util:map>
<!--    util:list-->
    <util:list id="listUtil">
        <list/>
        <value>sssss</value>
        <bean class="com.tc.bean.User">
<!--            为car赋值的时候。改变car的价格 -->
            <property name="cats" ref="cat2"/>
            <property name="cats.price" value="99000"/>
            <property name="map" ref="mapUtil"/>
        </bean>
        <ref bean="cat2"/>
    </util:list>
<!--    util:properties-->
    <util:properties id="propertiesUtil">
        <prop key="username">xiyang</prop>
        <prop key="password">12323</prop>
    </util:properties>
<!--    util:set-->
    <util:set id="setUtil">
        <value>root</value>
        <value>10000</value>
    </util:set>

1.7属性继承、配置抽象,bean创建的顺讯

<!-- 实验6:通过继承实现bean配置信息的重用 -->
<!--实验7:通过abstract属性创建一个模板bean -->
<!-- abstract="true":这个bean的配置是一个抽象的,不能获取他的实例,只能被别人用来继承 -->
    <bean class="com.tc.bean.User" id="user12" abstract="true">
        <property name="name" value="tancheng"/>
        <property name="sex" value="男"/>
        <property name="email" value="qq.com"/>
    </bean>
<!--    继承user12的配置信息 需要改的就改掉-->
    <bean id="user13" parent="user12" class="com.tc.bean.User">
        <property name="name" value="zhangsan"/>
    </bean>
<!--实验8:bean之间的依赖 -->
    <!-- 原来是按照配置的顺序创建bean -->
    <!-- 改变bean的创建顺序 -->
    <!--实验8:bean之间的依赖(只是改变创建顺序) -->
   <bean class="com.tc.bean.User" id="user14" depends-on="cat,user12"></bean>
    <bean class="com.tc.bean.Cat" id="cat"></bean>

1.8.bean的作用域(单例and多例模式)

<!-- 实验9:测试bean的作用域,分别创建单实例和多实例的bean★bean的作用域:
指定bean是否单实例,xxx;
默认:单实例的
prototype:多实例的:容器启动默认不会去创建对象获取的时候创建对象、每次获取都会创建一个新的对象
singleton:单实例的;默认的 在容器启动完成之前就已经创建好对象,保存在容器中了。任何获取都是获取之前创建好的那个对象;
 request:在web环境下,同一次请求创建一个Bean实例(没用)
 session:在web环境下,同一次会话创建一个Bean实例(没用)
 -->
<bean class="com.tc.bean.User" id="user" scope="prototype"/>

2工厂

2.1静态工厂

创建工厂类

import com.tc.bean.Cat;
​
/**
 * @author 谭铖
 * @date 2021/6/8 18:16
 * 静态工厂
 */
public class CatStaticFactory {
    public static Cat getCat(String name){
        System.out.println("CatStaticFactory...");
        Cat cat = new Cat();
        cat.setName(name);
        cat.setPrice(13232312);
        return cat;
    }
}

配置xml

 <!--实验5:配置通过静态工厂方法创建的bean、实例工厂方法创建的bean、FactoryBean★ -->
    <!-- bean的创建默认就是框架利用反射new出来的bean实例 -->
    <!--
    工厂模式;工厂帮我们创建对象;有一个专门帮我们创建对象的类,这个类就是工厂 AirPlane ap = AirPlaneFactory.getAirPlane(String jzName);
    静态工厂:工厂本身不用创建对象;通过静态方法调用,对象 = 工厂类.工厂方法名();
    实例工厂:工厂本身需要创建对象;工厂类 工厂对象 = new 工厂类(); 工厂对象.getAirPlane("张三"); -->
<!--    静态工厂-->
<!--
    静态工厂(不需要创建工厂本身)factory-method="getCat":指定哪个方法是工厂方法
    class:指定静态工厂全类名 factory-method:指定工厂方法
    constructor-arg:可以为方法传参
-->
    <bean class="com.tc.Factory.CatStaticFactory" id="cat1" factory-method="getCat">
        <constructor-arg name="name" value="奥迪"/>
    </bean>

2.2实例工厂

创建实例工厂

package com.tc.Factory;
​
import com.tc.bean.Cat;
​
/**
 * @author 谭铖
 * @date 2021/6/8 18:21
 */
public class CatFactory {
    public  Cat getCat(String name){
        System.out.println("CatFactory...");
        Cat cat = new Cat();
        cat.setName(name);
        cat.setPrice(13232312);
        return cat;
    }
}
​

配置

 <!--实例工厂使用 首先要先创建工厂方法 -->
    <bean class="com.tc.Factory.CatFactory" id="catFactory"/>
<!--    创建bean调用实例工厂
        factory-bean:获取创建的实例工厂
        factory-method:获取工厂的指定方法
         constructor-arg:可以为方法传参
-->
    <bean class="com.tc.bean.Cat" id="cat" factory-bean="catFactory" factory-method="getCat">
    <!-- constructor-arg:可以为方法传参-->
        <constructor-arg name="name" value="宝马"/>
    </bean>

2.3FactoryBean

创建类实现FactoryBean

package com.tc.Factory;
​
import com.tc.bean.Cat;
import org.springframework.beans.factory.FactoryBean;
​
/**
 * @author 谭铖
 * @date 2021/6/8 21:02
 * 1、编写一个FactoryBean的实现类
 * 2、在spring配置文件中进行注册
 */
public class MyFactorylmpl  implements FactoryBean<Cat> {
    /**
     * getObject:工厂方法;
     * 返回创建的对象
     */
    @Override
    public Cat getObject() throws Exception {
        System.out.println("MyFactorylmpl。。帮你创建对象...");
        Cat cat = new Cat();
        cat.setName("保时捷");
        return cat;
    }
​
    /**
     * 返回创建对象的类型
     *  Spring会自动调用这个方法来确认创建的对象是什么类型
     * @return
     */
    @Override
    public Class<?> getObjectType() {
        return Cat.class;
    }
​
    /**
     * 判断是否是单列多列 但是创建都是获取再创建对象
     * false:不是单例
     * true:是单例
     * @return
     */
    @Override
    public boolean isSingleton() {
        return false;
    }
}
​

配置

 <!--
    FactoryBean★(是Spring规定的一个接口)只要是这个接口的实现类,Spring都认为是一个工厂;
        1、ioc容器启动的时候不会创建实例
        2、FactoryBean;获取的时候的才创建对象
-->
<!--  这里虽然调用的是MyFactorylmpl但是其实是创建的类里面的泛型的值-->
    <bean class="com.tc.Factory.MyFactorylmpl" id="myFactorylmpl"/>

2.4bean的生命周期

<!-- 实验10:创建带有生命周期方法的bean 生命周期:bean的创建到销毁;
 ioc容器中注册的bean;
 1.单例bean,容器启动的时候就会创建好,容器关闭也会销毁创建的bean2)
 2.多实例bean,获取的时候才创建;我们可以为bean自定义一些生命周期方法;
 spring在创建或者销毁的时候就会调用指定的方法;自定义初始化方法和销毁方法;
 init-method:初始化方法
 destroy-method:销毁方法
  -->
<bean class="com.tc.bean.Cat" id="cat" init-method="init" destroy-method="destroy"/>

cat配置方法

/**
 * @author 谭铖
 * @date 2021/6/7 22:59
 */
@Data
@AllArgsConstructor
public class Cat {
    private String name;
    private Integer price;
​
    public Cat() {
        System.out.println("cat构造方法");
    }
​
 //    初始化方法
    public void init(){
        System.out.println("初始化");
    }
//    销毁方法
    public void destroy(){
        System.out.println("销毁方法");
    }
}

2.5后置处理器

顺序:

容器启动)构造器------后置处理器before..-----初始化方法-----后置处理器after...-----bean初始化完成 无论bean是否有初始化方法;后置处理器都会默认其有,还会继续工作;

使用首先是接口就创建类实

package com.tc.bean;
​
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
​
/**
 * @author 谭铖
 * @date 2021/6/9 16:12
 * bean的后置处理器
 * 1)、编写后置处理器的实现类
 * 2)、将后置处理器注册在配置文件中
 */
public class BeanPost implements BeanPostProcessor {
    /**
     * 初始化开始之前调用
     * @param bean 返回bean
     * @param beanName bean在xml中配置的id
     * @return 返回bean
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization...【"+beanName+"】" +
                "bean将要调用初始化方法了....这个bean是这样:【"+bean+"】");
        //初始化之后返回的bean;返回的是什么,容器中保存的就是什么
        return bean;
    }
​
    /**
     * 在初始化之后调用
     * @param bean 返回bean
     * @param beanName bean在xml中配置的id
     * @return 返回bean
     * @throws BeansException
     */
​
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization...【"+beanName+"】" +
                "bean初始化方法调用完了...AfterInitialization..");
        //初始化之后返回的bean;返回的是什么,容器中保存的就是什么
        return bean;
    }
}
​

添加xml

只要配置后置处理器不管怎样都会运行

  <!--实验11:测试bean的后置处理器:BeanPostProcessorSpring有一个接口:
    后置处理器:可以在bean的初始化前后调用方法; -->
    <bean class="com.tc.bean.BeanPost" id="beanPost"/>

2.6数据库连接池

!--实验12:引用外部属性文件★依赖context名称空间 -->
    <!-- 数据库连接池作为单实例是最好的;一个项目就一个连接池,连接池里面管理很多连接。连接是直接从连接池中拿 -->
    <!-- 可以让Spring帮我们创建连接池对象,(管理连接池) -->
    <!--加载外部配置文件 固定写法classpath:,表示引用类路径下的一个资源-->
    <!--引入数据库配置信息 -->
<!--    <context:property-placeholder location="classpath:jdbc.properties"/>-->
​
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="root"/>
        <property name="password" value="123456"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/bookshopping?serverTimezone=UTC"/>
        <property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
    </bean>

test

public class UserTest04 {
    ApplicationContext applicationContext = new
            ClassPathXmlApplicationContext("conf/applicationcontext1.xml");
//    数据库连接池
    @Test
    public void userTest() throws SQLException {
//        获取数据库
        DataSource bean = applicationContext.getBean(DataSource.class);
        System.out.println(bean.getConnection());
    }
}

3.xml的自动装配

    <!-- 为Person里面的自定义类型的属性赋值
    property:手动赋值自动赋值(自动装配)/自动装配:(仅限于对自定义类型的属性有效)
         1)、先按照有参构造器参数的类型进行装配(成功就赋值);没有就直接为组件装配null即可。
         2)、如果按照类型找到了多个;参数的名作为id继续匹配;找到就装配;找不到就null;
         3)、不会报错;自动的为属性赋值: -->
    <bean class="com.tc.bean.Cat" id="cats">
        <property name="name" value="baoma"/>
        <property name="price" value="23112"/>
    </bean>
<!--
    autowire="default/no":不自动装配;不自动为car属性赋值 //按照某种规则自动装配
    autowire="byName":按照名字;以属性名(car)作为id去容器中找到这个组件,给他赋值;如果找不到就装配null;
    autowire="byType":以属性的类型作为查找依据去容器中找到这个组件;如果容器中有多个这葛类型的组件,报错;
    autowire="constructor":public Person(Car car) 按照构造器进行赋值首先要创建构造方法;
        1)、先按照有参构造器参数的类型进行装配(成功就赋值);没有就直接为组件装配null即可。
         2)、如果按照类型找到了多个;参数的名作为id继续匹配;找到就装配;找不到就null;
         3)、不会报错;自动的为属性赋值
-->
    <bean class="com.tc.bean.User" id="user" autowire="constructor"/>

5.SpEL

Spring表达式语言在SpEL中使用字面量、引用其他bean、引用其他bean的某个属性值、

  • 用#{}使用可以完成一些字符串完成不了赋值

<!--
实验14:[SpEL测试I](Spring Expression Language)
Spring表达式语言在SpEL中使用字面量、引用其他bean、引用其他bean的某个属性值、
【 调用非静态方法调用静态方法、】使用运算符;都支持
-->
<bean class="com.tc.bean.User" id="user2">
    <!-- 字面量:${}; #{} -->
    <property name="name" value="#{10*10}"/>
    <!-- 引用其他bean的某个属性值、 -->
    <property name="sex" value="#{cats.name}"/>
    <!-- 调用非静态方法; 对象.方法名 -->
    <property name="email" value="#{cats.getName()}"/>
     <!-- 引用其他bean -->
    <property name="cats" value="#{cats}"/>
</bean>

4.注解

 

 

 

 

1.1context:exclude-filter 排除装配组件

1.2context:include-filter 指定装配组件

 

<!--
    使用注解配置步骤
    1.业务层等配置好注解
    2.添加自动扫描组件 context:component-scan base-package="com.tc"/>
            base-package:配置注解类的地址
    3.导入AOP jar包 支持注解
-->
    <context:component-scan base-package="com.tc" use-default-filters="false" >
<!--    扫描的时候排除一些组件 context:exclude-filter
    type:根据什么排除
        annotation 根据注解排除
            expression:注解全类名
        assignable 排除具体的某个类
            expression: 类全类名
 -->
   <context:exclude-filter type="assignable" expression="org.springframework.stereotype.Repository"/>&ndash;&gt;-->
<!--
    context:include-filter 只扫描那些组件
     指定只扫描哪些组件,默认是全都扫描进来
        所以需要设置use-default-filters="false"
-->
        <context:include-filter type="assignable" expression="org.springframework.stereotype.Repository" />
    </context:component-scan>

1.3配置

  • 数据库层(DAO) @Repository

  • 业务层(service) @Service

  • 控制器(Servlet) @Controller

  • 全部层可以配置 @Component

/**
 * @author 谭铖
 * @date 2021/6/10 15:06
 * 持久层数据库层用@Repository
 * 注解类未配置id id为类名的首字母小写 注解前面加括号可以自定义id
 */
@Repository("password")
/**
 * 单实例 singleton
 * 多实例 prototype
 */
@Scope("prototype")
public class UserDAO {
​
}

2.依赖注入 @Autowired自动装配

//servlet层
@Controller
public class UserServlet {
    /**
     *  如果不去new对象就会空指针异常java.lang.NullPointerException
     *  用spring就可以自动装配了用注解@Autowired
     */
    @Autowired
    private UserService userService;
    public  void save(){
        System.out.println("调用userService");
        userService.save();
    }
}
​
//service层
@Service
public class UserService {
​
    @Autowired
    private UserDAO userDAO;
    public void save() {
        System.out.println("调用userDAO");
        userDAO.create();
    }
}
​
//DAO层
@Repository("password")
/**
 * 单实例 singleton
 * 多实例 prototype
 */
@Scope("prototype")
public class UserDAO {
    public void create() {
        System.out.println("保存用户");
    }
}
<!--    依赖注入 @Autowired自动装配 装配全部-->
    <context:component-scan base-package="com.tc"/>

 

 

2.设置两个相同的service

//父类
@Service
public class UserService {
​
    @Autowired
    private UserDAO userDAO;
    public void save() {
        System.out.println("调用userDAO");
        userDAO.create();
    }
}
​
​
//子类
@Service
public class UserService01 extends UserService {
    @Autowired
    private UserDAO userDAO;
    @Override
    public void save() {
        System.out.println("UserService01");
        userDAO.create();
    }
}
public class UserServlet {
    /**
     *  如果不去new对象就会空指针异常java.lang.NullPointerException
     *  用spring就可以自动装配了用注解@Autowired
     *      自动装配的步骤
     *          1.按照类的找
     *              找到装配/没找到异常
     *              找到多个 按照类名首字母小写为id找
     *                  找不到异常 可以用@Qualifier("userService01")在里面输入类名首字母小写的id
     *                      如果@Qualifier()配置的id不存在就会报异常
     *                          可以配置注解@Autowired(required = false)找不到赋值为null
     *
     */
//    自动装配配置为required的话找不到赋值变null
    @Autowired(required = false)
// 使用类名首字母小写的为id配置
    @Qualifier("userService011")
​
    private UserService userService011;
    public  void save(){
        System.out.println("调用userService"+userService011);
​
    }
}

2方法也可以配置自动装配

/**
 * 方法也可以自动装配
 * 在bean创建的时候就会运行
 * 方法上传的参数都会赋值
  */
@Autowired(required = false)
public void test(UserDAO userDAO, @Qualifier("userService") UserService userService){
    System.out.println("spring运行:"+userDAO+"and"+userService);
}

3.@Autowired 和@Resource的区别

@Resource是javaee的标准 在哪里都可以用 扩展性强

 

3.spring的单元测试

 

4.自动装配泛型

1.dao层配置一个baseDAO抽象方法

public abstract class baseDAO<T> {
//    抽象方法
   public abstract void save();
}

2.dao层catDAO继承baseDAO

/**
 * @author 谭铖
 * @date 2021/6/11 1:37
 * 数据库层装配
 */
@Repository
public class CatDAO extends baseDAO<Cat>{
​
    @Override
    public void save() {
        System.out.println("购物车");
    }
}

3.service层baseService通用类

public class baseService<T> {
//    自动装配
    @Autowired
    baseDAO<T> baseDAO;
​
    public void save(){
    baseDAO.save();
    }
}

4.继承baseService

/**
 * @author 谭铖
 * @date 2021/6/11 1:41
 */
@Service
public class CatService extends baseService<Cat>{
}

5.xml装配

<!--    依赖注入 @Autowired自动装配-->
    <context:component-scan base-package="com.tc"/>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水果不是橙子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值