spring基础1(IOC)

1、IOC(控制反转)

​ 即控制反转,它不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。

(1)控制了什么?

​ 是 bean 的创建、管理的权利,控制 bean 的整个生命周期。

(2)反转了什么?

​ 把这个权利交给了 Spring 容器,而不是自己去控制,就是反转。由之前的自己主动创建对象,变成现在被动接收别人给我们的对象的过程,这就是反转。

(3)bean 又是什么?

​ Bean 其实就是包装了的 Object,无论是控制反转还是依赖注入,它们的主语都是 object,而 bean 就是由第三方包装好了的 object。

2、DI(依赖注入)

​ 即依赖注入:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

(1)依赖什么?

​ 程序运行需要依赖外部的资源,提供程序内对象的所需要的数据、资源。

(2)注入什么?

​ 配置文件把资源从外部注入到内部,容器加载了外部的文件、对象、数据,然后把这些资源注入给程序内的对象,维护了程序内外对象之间的依赖关系。

3、IOC和DI总结

​ 控制反转是通过依赖注入实现的。但是它们是有差别的,像是从不同角度描述的同一件事。

  • IoC 是设计思想,DI 是具体的实现方式;

  • IoC 是理论,DI 是实践;

    ​从而实现对象之间的解藕。

    ​当然,IoC 也可以通过其他的方式来实现,而 DI 只是 Spring 的选择。IoC 和 DI 也并非 Spring 框架提出来的,Spring 只是应用了这个设计思想和理念到自己的框架里去。

(1)为什么使用IOC

​ 解藕。

​ 它把对象之间的依赖关系转成用配置文件来管理,由 Spring IoC Container 来管理。在项目中,底层的实现都是由很多个对象组成的,对象之间彼此合作实现项目的业务逻辑。但是,很多很多对象紧密结合在一起,一旦有一方出问题了,必然会对其他对象有所影响,所以才有了解藕的这种设计思想。

优质博客:依赖注入和控制反转的理解,写的太好了。-CSDN博客

4、代码实现

(1)使用xml实现注入

  1. 目录结构

  2. Bean
    Address类:

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Address {
        String name;
    }
    

    User类(包含address类)

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        private String name;
        private Address address;
        private String[] book;
        private List<String> hobby;
        private Map<String,String> card;
        private Set<String> games;
        private String wife;
        private Properties info;
    }
    
  3. xml
    其中bean标签的作用是把对应的类注入容器,id是类的唯一标识,name是类的别名,都可以以此为根据实例化。
    property标签是类的属性,name和对应属性名相同,如果类型是String就可以用value直接指定值,如果是另外一个已经注入容器的Bean就可以使用ref指定Bean的id,其他类型的注入如下

    <?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
           https://www.springframework.org/schema/context/spring-context.xsd">
        <context:annotation-config/>
        <bean id="user" class="com.zhangxin.spring.pojo.User" name="U,u">
            <property name="name" value="zhangxin"/>
            <property name="address" ref="address"/>
            <property name="book">
                <array>
                    <value>《红楼梦》</value>
                    <value>《水浒传》</value>
                    <value>《三国演义》</value>
                </array>
            </property>
            <property name="hobby">
                <list>
                    <value>唱歌</value>
                    <value>跳舞</value>
                </list>
            </property>
            <property name="card">
                <map>
                    <entry key="身份证" value="pwd1"/>
                    <entry key="银行卡" value="pwd2"/>
                </map>
            </property>
            <property name="games">
                <set>
                    <value> cf</value>
                    <value> 王者</value>
                    <value> cf</value>
                </set>
            </property>
            <property name="wife">
                <null/>
            </property>
            <property name="info">
                <props>
                    <prop key="学号">20210222</prop>
                    <prop key="专业">软件工程</prop>
                </props>
            </property>
        </bean>
    
        <bean id="address" class="com.zhangxin.spring.pojo.Address" >
                <property name="name" value="郑州"/>
        </bean>
    
    </beans>
    
  4. Test

    public class MyTest {
        @Test
        public void testUser(){
            ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
            User user = context.getBean("u",User.class);
            System.out.println(user);
        }
    }
    

    测试结果:

(2)使用注解实现注入

  1. Bean
    Dog类

    @Component
    public class Dog {
        public void shut(){
            System.out.println("狗叫!");
        }
    }
    

    Cat类

    @Component
    public class Cat {
        public void shut(){
            System.out.println("猫叫!");
        }
    }
    

    People类

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Component
    public class People {
        @Value("张三")
        String name;
        @Autowired
        Cat cat;
        @Autowired
        Dog dog;
    }
    
    
  2. Test

    public class MyTest {
        @Test
        public void test1(){
            ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
            People person = context.getBean("people", People.class);
            person.getCat().shut();
            person.getDog().shut();
            System.out.println(person);
        }
    }
    

    img

  3. xml
    这个xml文件的核心就是 <context:component-scan base-package=“com.zhangxin.pojo”/> 这一行,下面可以使用定义SpringConfig配置类实现无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: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
           https://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:annotation-config/>
    <!--    扫描包,下包下的所有注解生效-->
        <context:component-scan base-package="com.zhangxin.pojo"/>
    
    </beans>
    
  4. Spring的Config类
    @Configuration 指定这个是配置类,@ComponentScan(“com.zhangxin.pojo”) 指定需要扫描bean的包使其注解生效。

    @Configuration
    @ComponentScan("com.zhangxin.pojo")
    public class MyConfig {
    
    }
    
  5. xml和config配置类从容器中取出bean的区别
    xml,需要使用spring配置文件

     ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
     People person = context.getBean("people", People.class);
    

    config,需要对应config的Class

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
    People people = context.getBean("people", People.class);
    

  6. 注解解释
    @Component
    表示这个类被spring接管了,即这个类已经注册为bean了
    @Componen的衍生注解:

    @Repository 该注解用于数据访问层的bean定义,数据访问层也就是我们常写的dao层、mapper层
    @Service 该注解用于业务逻辑层的bean定义,即service层
    @Controller 该注解用于表现层,控制层的bean定义,即controlle层等
    这四个注解的功能一样的都是把类注入spring,装配bean

    @Configuration
    表示这个类是一个配置类,也会注入spring,因为也是一个@Component

    @ComponentScan(“com.zhangxin.pojo”)
    表示要扫描的包com.zhangxin.pojo下的所有注解,不然这个包的注解不生效,相当于xml的 < context:component-scan base-package=“com.zhangxin.pojo”/> ,该注解只能使用1次,如果有多个需要扫描的包,使用下述方式实现

    @ComponentScan({"com.zhangxin.dao","com.zhangxin.service"})
    

    @Bean
    用于方法上,通常是是以一个方法的返回值的形式注入一个Bean,当然前提是这个方法对应的类是一个组件,比如下面的代码就是成功注入了Cat类,Cat类并没有使用@Component标签
    @Component , @Repository , @ Controller , @Service 这些注解只局限于自己编写的类,而@Bean注解能把第三方库中的类实例加入IOC容器中并交给spring管理

    public class Cat {
        public void shut(){
            System.out.println("猫叫!");
        }
    
    }
    @Component
    class A{
        @Bean
        Cat cat(){
            return  new Cat();
        }
    }
    

    @Value
    普通类型直接用value赋值,直接在属性上面

    @Resource(name=" ")
    如果没有指定name属性,当注解写在字段上时,默认取字段名,按照名称查找。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配

    @Autowired
    默认是byType可以使用@Qualifier指定Name,@Resource默认ByName如果找不到则ByType

    @Autowired可以和@Override配合使用
    比如某个属性类是个接口但是有多个实现类,默认情况是@Autowired标签会自动加载其中的一个实现类,然后使用这个实现类。这时候就需要特定加载某个类了

    • 第一步将实现类注册为一个Bean(@Service、@Repository标签都可以将类注册为bean)
    • 第二步使用@Qualifier(“beanId”)标签将bean的Id作为参数使用,加载特定的类。Id一般默认是bead名称首字母小写
         @Component
         // 指明bean名称
         @Qualifier("fooFormatter")
         public class FooFormatter implements Formatter {
             public String format() {
                 return "foo";
             }
         }
         @Component
         // 指明bean名称
         @Qualifier("barFormatter")
         public class BarFormatter implements Formatter {
             public String format() {
                 return "bar";
             }
         }
         @Component
         public class FooService {
            @Autowired
            // 同样使用@Qualifier进行指明注入
            @Qualifier("fooFormatter")
            private Formatter formatter;
         }
    

    @Import(ConfigB.class)
    可以在一个配置类引入另一个配置类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值