Spring学习笔记

spring

1.1 简介

    
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>

    <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.2.9.RELEASE</version>
    </dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>

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

1.2,优点

  • spring 是一个开源的免费的框架(容器)
  • spring是一个轻量级的,非侵入式的框架
  • 控制反转(IOC),面向切面编程(AOP)
  • 支持十五处理,对框架整合支持

1.3,spring的组成

The following diagram shows a high-level view of how Spring works. Your application classes are combined with configuration metadata so that, after the ApplicationContext is created and initialized, you have a fully configured and executable system or application.

Snipaste_2020-11-21_22-41-03

1.4,扩展

  • spring boot
    • 一个快速的开发脚手架
    • 基于Springboot可以快速的开发单个微服务
    • 约定大量配置
  • spring cloud
    • springcloud是基于Springboot实现的

因为现在大多数的公司都在使用Spring Boot进行快速的开发,学习springboot的前提需要掌握spring,springmvc。承上启下。

弊端:发展太久之后,违背了原来的理念!配置十分繁琐,人称:“配置地狱

1.5 IOC理论(控制反转)

在面向对象的传统方式中,获取对象的方式通常是用new关键字主动创建一个对象。spring中的Ioc方式对象的生命周期有spring框架提供的ioc容器来管理,直接从IoC容器中获取一个对象,控制权从应用程序交给了IoC容器。理论上是借助于“第三方”实现具有依赖关系对象之间的解耦,如下图,即把各个对象类封装之后,通过IoC容器来关联这些对象类。这样对象于对象之间就通过IoC容器进行联系,而对象与对象之间就没有什么联系。

应用程序没有引入IoC容器之前,对象A依赖对象B,那么A对象在实例化或者运行到某一点的时候,自己必须主动创建对象B或者使用已经创建好的对象B,其中无论是创建还是使用自己创建的对象B控制权都在应用程序自身。如果应用程序引入IoC容器之后,对象A和对象B之间失去了直接联系,那么当对象A实例化和运行时,如果需要对象B,IoC容器就会主动创建一个对象B注入(依赖注入)到对象A所需要的地方。由此,对象A获得依赖对象B的过程,由主动行为变成被动行为,即把创建对象交给了IoC容器处理,控制权颠倒了过来,这就是所谓的控制反转。

​ 在之前的业务中,用户的需求可能会影响我们原来的代码,我们需要更具用户的需求区修改原来的代码!如果程序代码量十分巨大,修改一次的成本代价回十分昂贵!

我们可以使用一个set接口实现,已经发生了革命性的变化

    private UserDao userDao;
	//利用set进行动态实现值的注入
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

之前,程序是主动创建对象!控制权在程序员手中

使用set注入,程序不在具有主动性,而是变成了被动的接受对象!

这种思想从本质上解决了问题,我们程序员不用再去管理对象的创建,系统的耦合性大大降低,可以更加专注在业务逻辑上

​ 注意:事实上依赖注入和控制反转是对同一件事情的不同描述,从某个方面说,就是他们描述的角度不同。依赖注入是从应用程序的角度描述,即应用程序依赖容器创建并注入它所需要的外部资源;而控制反转是从容器的角度描述,即容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源。外部资源可以是外部文件或对象。

1.6 IoC创建对象的方式

  1. 使用无参构造函数创建对象,默认

  2. 使用有参构造函数创建对象。

    1. 下标赋值

          <!-- 第一种赋值,下标赋值 -->
          <bean id="user" class="com.qijian.pojo.User">
              <constructor-arg index="0" value="mahuahong"/>
          </bean>
      
    2. 类型赋值

          <bean id="user" class="com.qijian.pojo.User">
      <!--            类型赋值-->
      <!--        通过类型创建对象-->
              <constructor-arg type="java.lang.String" value="qijian"/>
          </bean>
      
    3. 通过参数名赋值

          <bean id="user" class="com.qijian.pojo.User">
      <!--        通过参数名创建对象-->
              <constructor-arg name="name" value="柒间"/>
      

      总结:在配置文件加载的时候,容器中管理的对象就已经初始化了。

2.1spring配置

  1. 别名,如果添加了别名也可以通过别名获取对象

    <alias name="user" alias="newname"/>
    
  2. Bean的配置

        <!--
        id : bean 的唯一标识,也就是相当于对象名
        class : bean 对象所对应的全限定名 : 包+类
        name : 也就是别名 可以同时取多个别名
    -->
        <bean id="us" class="com.qijian.pojo.User" name="user,us1"/>
    
  3. import 一般用于团队开发使用,它可以配置对各配置文件,导入合并为一个

    假设,现在项目中有多个人开发,这三个人复制不同的类开发,不同的类需要注册不同的Bean中,我们可以用import将所有的bean.xml合并为一个。只用的时候直接使用总的(applicationContex.xml)即可。

        <import resource="beans.xml"/>
         <import resource="beans1.xml"/>
    

3 依赖注入

3.1 构造器注入

3.2 Set方式注入【重点】

  • 依赖注入:Set注入!

    • 依赖:bean对象的创建依赖于容器
    • 注入:bean对象中的所有属性,由容器来注入
  • 【环境的搭建】

  • Address类

    public class Address {
        private String address;
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        @Override
        public String toString() {
            return "Address{" +
                    "address='" + address + '\'' +
                    '}';
        }
    }
    
  • Students类

    public class Student {
        private String name;
        private Address address;
        private String[] books;
        private List<String> hobbys;
        private Map<String,String> card;
        private Set<String> game;
        private String wife;
        private Properties info;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Address getAddress() {
            return address;
        }
    
        public void setAddress(Address address) {
            this.address = address;
        }
    
        public String[] getBooks() {
            return books;
        }
    
        public void setBooks(String[] books) {
            this.books = books;
        }
    
        public List<String> getHobbys() {
            return hobbys;
        }
    
        public void setHobbys(List<String> hobbys) {
            this.hobbys = hobbys;
        }
    
        public Map<String, String> getCard() {
            return card;
        }
    
        public void setCard(Map<String, String> card) {
            this.card = card;
        }
    
        public Set<String> getGame() {
            return game;
        }
    
        public void setGame(Set<String> game) {
            this.game = game;
        }
    
        public String getWife() {
            return wife;
        }
    
        public void setWife(String wife) {
            this.wife = wife;
        }
    
        public Properties getInfo() {
            return info;
        }
    
        public void setInfo(Properties info) {
            this.info = info;
        }
        public Student(){}
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", address=" + address.toString() +
                    ", books=" + Arrays.toString(books) +
                    ", hobbys=" + hobbys +
                    ", card=" + card +
                    ", game=" + game +
                    ", wife='" + wife + '\'' +
                    ", info=" + info +
                    '}';
        }
    }
    
    
  • bean.xml配置

        <bean id="address" class="com.qijian.pojo.Address"/>
        <bean id="student" class="com.qijian.pojo.Student">
            
    <!--        普通注入  value-->
            <property name="name" value="qijan"/>
            
    <!--        Beans注入 ref-->
            <property name="address" ref="address"/>
            
    <!--            数组注入  -->
            <property name="books">
                <array>
                    <value>think in java</value>
                    <value>计算机原理</value>
                    <value>SSM从入门到精通</value>
                </array>
            </property>
            
    <!--            list-->
            <property name="hobbys">
                <list>
                    <value>写代码</value>
                    <value>听歌</value>
                </list>
            </property>
    
    <!--        Map-->
            <property name="card">
                <map>
                    <entry key="身份证" value="000000000000"/>
                    <entry key="银行卡" value="1111111111"/>
    
                </map>
            </property>
    
    <!--        Set-->
            <property name="game">
                <set>
                    <value>王者荣耀</value>
                    <value>刺激战场</value>
                </set>
            </property>
    
    <!--        null-->
            <property name="wife">
                <null/>
            </property>
    
    <!--        properties-->
            <property name="info">
                <props>
                    <prop key="Driver">222222</prop>
                    <prop key="sex">男</prop>
                    <prop key="name">qijian</prop>
                    <prop key="pwd">root</prop>
                </props>
            </property>
    
        </bean>
    
  • 测试类

    import com.qijian.pojo.Student;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class mytest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
           Student student = (Student) context.getBean("student");
    
            System.out.println(student.toString());
    
            /*输出
            Student{
                    name='qijan',
                    address=Address{a
                        ddress='null'
                        },
                    books=[
                        think in java,
                        计算机原理,
                        SSM从入门到精通
                        ],
                    hobbys=[
                        写代码,
                        听歌
                        ],
                    card={
                            身份证=000000000000,
                            银行卡=1111111111
                            },
                    game=[
                           王者荣耀,
                           刺激战场
                           ],
                    wife='null',
                    info={
                        name=qijian,
                        Driver=222222,
                        sex=男,
                        pwd=root
                        }
                 }
    
             */
        }
    }
    
    

3.3,其他方式注入

需要注意的是c名命空间和p名命空间不能直接使用需要导入xml约束

c:

		xmlns:c="http://www.springframework.org/schema/c"

p:

       xmlns:p="http://www.springframework.org/schema/p"

User类

package com.qijian.pojo;

public class User {
    private String name;
    private int age;


    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

  1. p名命空间注入

    ** The p-namespace lets you use the bean element’s attributes (instead of nested <property/> elements) to describe your property values collaborating beans, or both.

    P-namespace **

    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:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
            <bean id="user" class="com.qijian.pojo.User"
                  p:name="qijian"
                  p:age="18"
            />
    
    </beans>
    
  2. c名命空间注入(通过构造器注入)

    Similar to the XML Shortcut with the p-namespace, the c-namespace, introduced in Spring 3.1, allows inlined attributes for configuring the constructor arguments rather then nested constructor-arg elements.

    ​ **与 p 名称空间的 XML Shortcut 类似,Spring 3.1中引入的 c 名称空间允许内联属性配置构造函数参数,而不是嵌套的构造函数-arg 元素。 **

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:c="http://www.springframework.org/schema/c"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="user" class="com.qijian.pojo.User">
            <constructor-arg name="name" value="柒间"/>
            <constructor-arg name="age" value="19"/>
        </bean>
    
            //c名命空间注入
        <bean id="user1" class="com.qijian.pojo.User" c:name="qijianc" c:age="18"/>
    
    
    </beans>
    

    c名命空间注入需要由有参构造函数

*** 注意 ***

Null and Empty String Values

//Spring 将属性和类似属性的空参数视为空字符串。下面的基于 xml 的配置元数据片段将 email 属性设置为空 String 值(“”)。
<bean class="ExampleBean">
    <property name="email" value=""/>
</bean>

上面相当于String email=“”;

//The <null/> element handles null values
<bean class="ExampleBean">
    <property name="email">
        <null/>
    </property>
</bean>

上面的注入等价于String email = null;

3.4 ,bean的作用域

1,单例模式(spring默认机制)

​ 只管理单一 bean 的一个共享实例,对 ID 或 ID 与 bean 定义相匹配的 bean 的所有请求都将导致 Spring 容器返回一个特定 bean 实例。

<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>

下面的图片展示了单例模式的工作原理:

2,原型模式

​ The non-singleton prototype scope of bean deployment results in the creation of a new bean instance every time a request for that specific bean is made. That is, the bean is injected into another bean or you request it through a getBean() method call on the container. As a rule, you should use the prototype scope for all stateful beans and the singleton scope for stateless beans.

​ Bean 部署的非单例原型范围导致每次对特定 bean 发出请求时都会创建一个新的 bean 实例。也就是说,bean 被注入到另一个 bean 中,或者您通过容器上的 getBean ()方法调用请求它。通常,您应该为所有有状态 bean 使用原型范围,为无状态 bean 使用单例范围。

<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>

下图说明了 Spring 的原型范围:

注意:每次从容器中get的时候,都会产生一个新的对象!

3,其余的request,session,application,这些只能在web开发中使用到!

4,bean的自动装配

环境:

Cat.class

package com.qijan.pojo;
public class Cat {
    public void shout(){
        System.out.println("miao~~~");
    }
}

Dog.class

package com.qijan.pojo;

public class Dog {
    public void shout(){
        System.out.println("wang~~");
    }
}

People.class

package com.qijan.pojo;

import com.qijan.pojo.Cat;
import com.qijan.pojo.Dog;

public class People {
    private String name;
    private Cat cat;
    private Dog dog;

    public String getName() {
        return name;
    }

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

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                "\n, cat=" + cat +
                "\n, dog=" + dog +
                '}';
    }
}

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

    <bean id="cat" class="com.qijan.pojo.Cat"/>
    <bean id="dog" class="com.qijan.pojo.Dog"/>
<!--    <bean id="people" class="com.qijan.pojo.People">-->
<!--        <property name="name" value="qijian"/>-->
<!--        <property name="dog" ref="dog"/>-->
<!--        <property name="cat" ref="cat"/>-->
<!--    </bean>-->

<!--    自动装配 byName:会自动在容器上下文查找,和自己对象set方法后面的值对应的bean id-->
    <bean id="people" class="com.qijan.pojo.People" autowire="byName">
        <property name="name" value="qijian"/>
    </bean>

</beans>

测试类

import com.qijan.pojo.People;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
    @Test
    public void test1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

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

        people.getCat().shout();
        people.getDog().shout();
        System.out.println(people.toString());
    }
}

  • 自动装配是Spring满足bean依赖的一种方式
  • Spring会在上下文寻找,并自动给bean装配属性!;

在spring中有三种装配方式

  • 在xml中显示的配置
  • 在Java中显示的配置
  • 隐式的自动装配bean【重要】

4.1,ByName自动装配

    <bean id="cat" class="com.qijan.pojo.Cat"/>
    <bean id="dog" class="com.qijan.pojo.Dog"/>
<!--    <bean id="people" class="com.qijan.pojo.People">-->
<!--        <property name="name" value="qijian"/>-->
<!--        <property name="dog" ref="dog"/>-->
<!--        <property name="cat" ref="cat"/>-->
<!--    </bean>-->

<!--    自动装配 byName:会自动在容器上下文查找,和自己对象set方法后面的值对应的bean id-->
    <bean id="people" class="com.qijan.pojo.People" autowire="byName">
        <property name="name" value="qijian"/>
    </bean>

4.2 byType自动装配

    <bean class="com.qijan.pojo.Dog"/>
    <bean class="com.qijan.pojo.Cat"/>
<!--    自动装配 byType: 会自动在容器上下文查找,和自己对象属性类型相同的bean
    可以不用设置bean id
    -->
    <bean id="people" class="com.qijan.pojo.People" autowire="byType">
        <property name="name" value="qijian"/>
    </bean>

小结:

  1. byName:需要保证bean的id的唯一,并且这个bean需要和自动注入的属性的set方法的值一致
  2. byType:需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性的类型一致!

4.4,使用注解实现自动装配

jdk1.5 开始支持注解,spring2.5开始支持注解

要使用注解须知:

  1. 导入约束

  2. 配置注解支持

    ​ 您可以将它们注册为单独的 bean 定义,但也可以通过在基于 xml 的 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"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://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/>//注解的支持,需要添加进去。
    
    </beans>
    

    @Autowired

    直接在属性上使用即可!也可以在set方法使用!

    使用Autowired我们可以不用编写Set方法,前提是你的这个自动装配的属性在(spring)容器中存在,且符合名字byname!

    @Nullable  字段标记了这个注解,说明这个字段可以为null
    
    public @interface Autowired{
        boolean required() default true;
    }
    

    代码测试:

    //使用在属性上

    //    如果显示定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空
    //    @Autowired(required = false)
        @Autowired
        private Cat cat;
    	public People(@Nullable Cat cat) {
       		 this.cat = cat;
    }
    
    

    //对构造函数应用@autowired 注释,如下面的例子所示:

    public class People{
        private String name;
        ...
        @Autowired
        public void People(String name){}
        ...
        
    }
    

    //可以将@autowired 注释应用于传统的 setter 方法,如下面的示例所示:

    public class People{
        private String name;
        ...
        @Autowired
        public void setName(String name){
            this.name = name;
    	}
    }
    

    //还可以将注释应用于具有任意名称和多个参数的方法等。

    如果@Autowired自动装配的环境比较复杂,自动装配无法通过注解【@AutoWired】完成的时候,我们可以使用@Qualifier(value="newcatName")去配合@Autowired的使用,指定一个唯一的bean对象注入

    public class People{
        @Autowired
        @Qualifier(value="newcatname")
        private Cat cat;
        
        @Autowired
        @Qualifier(value="nawdogname")
        private Dog dog;
        ...
    }
    

    注意:@Qualifier于@Autowired注解配合使用,会将默认的按bean类型装配修改为按Bean的实例名称装配,Bean的实例名称由@Qualifier注解的指定。

    ​ 从 Spring Framework 4.3开始,如果目标 bean 从一开始就只定义一个构造函数,那么在这样的构造函数上就不再需要@autowired 注释了。但是,如果有多个构造函数可用,并且没有主/默认构造函数,那么至少有一个构造函数必须用@autowired 注释,以便指示容器使用哪个构造函数。有关详细信息,请参阅关于构造函数解析的讨论。

  3. @resource功能比较强大,但是使用的较少

    public class People{
        @Resource(name="cat2")
        private Cat cat;
        
        @Resource
        private Dog dog;
        ...
    }
    

    注意:

    @Resource和@Autowired的区别

    • 都是用来自动装配的,都可以放在属性字段上
    • @Autowired通过byName的方式实现
    • @Resource默认通过byname的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就会报错!
    • 执行的顺序不同:@Autowired

5,使用注解开发

​ 在Spring4之后,要使用注解开发,必须要保证aop的包导入,使用注解需要导入context约束,增加注解的支持!

  1. bean

  2. 属性如何注入

    //java文件

    package com.qijian.pojo;
    
    import org.springframework.stereotype.Component;
    @Component
    public class User {
    
        private String name = "qijian";
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + 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"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd">
    
    <!--    指定扫描的包,这个包下的注解会生效-->
        <context:component-scan base-package="com.qijian.pojo"/>
    <!--    注解-->
        <context:annotation-config/>
    
    </beans>
    
  3. 衍生注解

    @Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层!

    • dao【@Repository】

    • service【@Service】

    • controller【@Controller】

      这四个注解功能时一样的,都是代表将莫格1类注册到Spring中

  4. 自动装配

    @Autowired,@Qualifier(value ="XXX"),@Resource

  5. 作用域

    @Scope 例如:@Scope("prototype") 写在类的上面

    @Component
    @Scope("prototype")
    public class People{
       // @Value("qijian")
        private String name; 
    	//相当于<property name="name" value="qijian">
        @Value("qijian")//写在此处与写在属性上面时一样的,但是如果复杂的注入时不建议使用
        public void setName(String name){
    		this.name=name;
        }
    }
    
  6. 小结:

    xml与注解

    • xml更加万能,适用于任何场合!维护简单方便

    • 注解不是自己类使用不了,维护相对复杂!

最佳实践:

  • xml用来管理bean;

  • 注解只负责完成属性的注入;

  • 使用过程中我们需要注意,要让注解生效,就必须开启注解的支持

    <!--    指定扫描的包,这个包下的注解会生效-->
        <context:component-scan base-package="com.qijian.pojo"/>
    <!--    注解-->
        <context:annotation-config/>
    

注意:

使用注解开发时,UerControllerDD user = context.getBean("uerControllerDD",UerControllerDD.class);前面的参数(bean的名字)需要最从一定的格式不然就不能够从容器中拿到对应的bean。只需要把该类的第一个字母小写放在其中就可以了。并且如果出现下面的情况那么注入的属性的值时由注解决定的。

@Value("柒间")
private String name = "qijan";

6,使用Java的方式配置Spring

qijianConfig.class

package com.qijian.config;

import com.qijian.dao.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

//这个也会被spring容器托管,注册到容器中,因为它本身就是一个@Conponent
//@Configuration代表这个是一个配置类,就和我们之前的beans.xml
@Configuration
@ComponentScan("com.qijian.dao")
@Import(qijianConfig2.class)//把qijianConfig2配置类导入
public class qijianConfig {

//注册一个bean,相当于我们之前的bean标签
//    这个方法的名字,就相当于bean标签的id属性
//    这个方法的返回值,就相当于bean标签中的class属性
    @Bean
    public User getUser(){

        return new User();//返回注入到bean的对象
    }

}

qijianConfig.class

package com.qijian.config;

public class qijianConfig2 {
}

User.class

package com.qijian.dao;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

//这里这个注解的意思就是说明这个类被spring接管了,注册到了容器中
@Component
public class User {
    private String name ;

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

    public String getName() {
        return name;
    }

    @Value("qijian")
    public void setName(String name) {
        this.name = name;
    }
}

MyTest.class

import com.qijian.config.qijianConfig;
import com.qijian.dao.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyTest {
    
    @Test
    public void Test1(){
        //如果完全使用了配置类方式去做,我们只能通过AnnotationConfig上下文来获取容器,通过配置文件获取class对象加载
        ApplicationContext context = new AnnotationConfigApplicationContext(qijianConfig.class);

        User user = context.getBean("getUser", User.class);

        System.out.println(user.toString());
        }

}

7,代理模式

角色分析

  • 抽象角色:一般会用接口或者抽象类来解决

  • 真实角色:被代理的角色

  • 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作

  • 客户:访问代理对象的人

代码步骤:

  1. 接口

    public interface Rent {
        public void rent();
    }
    

真实角色:

public class Host implements Rent {
    public void rent() {
        System.out.println("出租房子");
    }
}
  1. 代理角色:

    public class Proxy {
        private Host host;
    
        public Proxy(){}
    
        public Proxy(Host host){
            this.host=host;
        }
        public  void rent(){
            seeHouse();
            host.rent();
            heTong();
            fare();
        }
    
        //看房
        public void seeHouse(){
            System.out.println("中介看房");
    
        }
    
        //
        public void heTong(){
            System.out.println("签订和同");
        }
    
        //收中介费
        public void fare(){
            System.out.println("收中介费");
        }
    }
    
  2. 客户段访问代理角色

    public class Client {
        public static void main(String[] args) {
            //房东出租房子
            Host host = new Host();
    
    //    代理,中介帮房东出租,代理角色一般会有些附属操作!
            Proxy proxy = new Proxy(host);
    
            //不用面对房东直接找中介,租房就可以了
    
            proxy.rent();
        }
    
    }
    
    

代理模式的好处:

  • 可以使真实角色的操作更加纯粹!不用区关注一些公共业务
  • 公共业务交给代理角色!实现了业务的分工!
  • 公共业务发生拓展的时候,方便集中管理!

缺点:

  • 一个真实的角色就会产生一个代理的角色;代码量会翻倍~开发效率变慢
posted @ 2021-03-05 22:32  柒间  阅读(67)  评论(0编辑  收藏  举报