2021-08-25

6、依赖注入

6.1、构造器注入

  1. 使用无参构造创建对象,这是Spring默认的!

  2. 假设我们要使用有参构造创建对象。

    创建实体类:

    package com.feng.pojo;
    
    public class User {
        private String name;
    
        public User(String name) {
            this.name = name;
        }
    
        public void show(){
            System.out.println(this.name);
        }
    }
    
    1. 下标赋值(有参构造方法里面参数的下标,从0开始)

      <!--通过下标赋值,有参构造方法中参数的下标,从零开始-->
          <bean id="user" class="com.feng.pojo.User">
              <constructor-arg index="0" value="小明"/>
          </bean>
      
    2. 通过类型赋值(有参构造方法中参数的类型)

      <!-- 第二种方式:通过类型创建,不建议使用!如果两个参数的类型相同怎么办   -->
          <bean id="user" class="com.feng.pojo.User">
              <constructor-arg type="java.lang.String" value="小红"/>
          </bean>
      
    3. 直接通过参数名来进行设置(掌握这个就够用了)

      <!--第三种:直接参数名设置-->
          <bean id="user" class="com.feng.pojo.User">
              <constructor-arg name="name" value="小黄"/>
          </bean>
      

6.2、Set方式注入【重点 】

  • 依赖注入:Set注入!
    • 依赖:bean对象的创建依赖于容器!
    • 注入:bean对象中的所有的属性,由容器来注入!
  1. 实体类

    package com.feng.pojo;
    
    import java.util.*;
    
    public class Student {
        private String name;
        private Address address;
        private String[] books;
        private List<String> hobbys;
        private Map<String,String> card;
        private Set<String> games;
        private String wife;
        private Properties info;
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", address=" + address.toString() +
                    ", books=" + Arrays.toString(books) +
                    ", hobbys=" + hobbys +
                    ", card=" + card +
                    ", games=" + games +
                    ", wife='" + wife + '\'' +
                    ", info=" + 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> getGames() {
            return games;
        }
    
        public void setGames(Set<String> games) {
            this.games = games;
        }
    
        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;
        }
    }
    
    package com.feng.pojo;
    
    public class Address {
        private String address;
    
        @Override
        public String toString() {
            return "Address{" +
                    "address='" + address + '\'' +
                    '}';
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    }
    
    
  2. 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">
    
        <bean id="address" class="com.feng.pojo.Address">
            <property name="address" value="上海"></property>
        </bean>
    
        <bean id="student" class="com.feng.pojo.Student">
            <property name="name" value="小明"/>
    
            <property name="address" ref="address">
    
            </property>
    
            <property name="books">
                <array >
                    <value >三国演绎</value>
                    <value >西游记</value>
                    <value >西游记</value>
                </array>
            </property>
    
            <property name="hobbys">
                <list>
                    <value>听歌</value>
                    <value>看电影</value>
                </list>
            </property>
    
            <property name="card">
                <map>
                    <entry key="123" value="123456"></entry>
                    <entry key="000" value="00000"></entry>
                </map>
            </property>
    
            <property name="games">
                <set>
                    <value>set1</value>
                    <value>set2</value>
                </set>
            </property>
    
            <property name="wife" >
                <null/>
            </property>
    
            <property name="info" >
                <props >
                    <prop key="name">小明</prop>
                    <prop key="pwd">123456</prop>
                    <prop key="admin">xiaoming</prop>
                </props>
            </property>
        </bean>
    </beans>
    
  3. 测试类

    package com.feng.studenttest;
    
    import com.feng.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='小明',
            //        address=Address{address='上海'},
            //        books=[三国演绎, 西游记, 西游记],
            //        hobbys=[听歌, 看电影],
            //        card={123=123456,
            //              000=00000},
            //        games=[set1, set2],
            //        wife='null',
            //        info={admin=xiaoming,
            //              name=小明,
            //              pwd=123456}}
    
        }
    }
    

6.3、拓展方式注入

我们可以使用p命名空间和c命名空间进行注入

使用前需要引入关于它的头文件:

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

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

使用:

<?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"
       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">

<!--这里体现了依赖注入的两种方试:
    方式一:set注入
    方式二:构造注入
-->

    <!--使用p命名空间注入属性,就是 property标签 就是给属性复制,p:属性名=“属性值” -->
    <bean id="user" class="com.feng.pojo.User" p:name="小明" p:age="18"/>

    <!--使用c命名空间注入,就是constructor-arg标签 前提是必须要有有参构造函数-->
    <bean id="user1" class="com.feng.pojo.User" c:name="小红" c:age="16"/>
    
</beans>

注意点:p命名注入和c命名注入不能直接使用,需要导入xml约束!!

6.4、bean的作用域

在这里插入图片描述

  1. singleton 单例模式(Spring默认机制 ,所有东西都是单例的)

    • 不管你在测试的时候你getbean几次user2,得到的对象地址始终是相等的

      在这里插入图片描述

        <!--你也可以将这个对象显示的定义为单例模式(即全局唯一)-->
        <bean id="user2" class="com.feng.pojo.User" scope="singleton"/>
    
  2. protoype

    • 原型模式刚好和单例模式相反,它是你getBean几次user3,他每一次得到的对象是不同的

    • 即每次从容器中get的时候,都会产生一个新的对象

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cVlJVdty-1629891802080)(C:\Users\江湖烽子\Pictures\Camera Roll\2021-08-25_100858.jpg)]

        <!--你也可以将这个对象设置为原型模式-->
        <bean id="user3" class="com.feng.pojo.User" scope="prototype"/>
    
  3. 其余的request、session、application、这些个只能在web开发中使用到!

7、Bean的自动装配

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

在Spring中有三种装配的方式

  1. 在XML中显示的配置
  2. 在Java中显示配置
  3. 隐式的自动装配bean【重要】

7.1、测试

环境搭建

  • 一个人有两个宠物

非自动装配:

<bean id="cat" class="com.feng.pojo.Cat"/>
    <bean id="dog" class="com.feng.pojo.Dog"/>

    <bean id="people" class="com.feng.pojo.People">
        <property name="name" value="小明"/>
        <property name="cat" ref="cat"/> //这里现在要自己手动装配
        <property name="dog" ref="dog"/>
    </bean>

7.2、ByName自动装配

  • byName: 会自动在容器上下文中查找,和自己对象set方法后面的值对应的bean 的id
 <!--现在我们让他自动去找 cat 和 dog-->
    <!--
    byName: 会自动在容器上下文中查找,和自己对象set方法后面的值对应的bean 的id
    -->
    <bean id="people2" class="com.feng.pojo.People" autowire="byName">
        <property name="name" value="小航"/>
    </bean>

7.3、ByType自动装配

    <bean  class="com.feng.pojo.Cat"/>
    <bean  class="com.feng.pojo.Dog"/>

<!--
        byType: 会自动在容器上下文中查找,和自己对象属性类型相同的bean,
			这里的类型是:com.feng.pojo.Cat
					    com.feng.pojo.Dog
        -->
    <bean id="people3" class="com.feng.pojo.People" autowire="byType">
        <property name="name" value="小红"/>
    </bean>

小结:

  • 在byName的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法后面的值一致!
  • byType的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致!

7.4、使用注解实现自动装配

jdk1.5支持的注解,Spring2.5就支持注解了!

要使用注解须知:

  1. 导入约束 context约束

  2. 配置注解的支持 < context:annotation-config/>

    <?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方法了,前提是你这个自动装配的属性在IOC(Spring)容器中存在,且符合名字byName

知识拓展:

@Nullable 字段标记了这个注解,说明这个字段可以为null;
public @interface Autowired {
    boolean required() default true;
}
public class People {
    //如果显示定义了Autowired的required属性为false,说明这个对象可以为null
    @Autowired(required = false)
    private Dog dog;
    @Autowired
    private Cat cat;
    private String name;
}

如果一个类要在xml中装配多个对象,那这时 @Autowired一个注解就搞不定了;

	 <bean id="cat" class="com.feng.pojo.Cat"/>
    <bean id="dog" class="com.feng.pojo.Dog"/>
    <bean id="cat11" class="com.feng.pojo.Cat"/>
    <bean id="dog11" class="com.feng.pojo.Dog"/>
    <bean id="people" class="com.feng.pojo.People"></bean>

这时我们可以使用@Qualifier(value=“XXX”)去配和@Autowired的使用,去指定一个唯一的bean对象注入

public class People {
    @Autowired()
    @Qualifier(value = "dog11")
    private Dog dog;
    @Autowired
    @Qualifier(value = "cat11")
    private Cat cat;
    private String name;
}

这样就可以了:@Autowired装配上面两个, @Qualifier装配下面两个。

开发中最常用的是@Autowired注解!!!

@Resource注解

public class People {

    @Resource(name = "dog2")
    private Dog dog;
 	@Resource
    private Cat cat;
    private String name;
}

小结:

  • @Resource 和 @Autowired 的区别:
    • 都是用来自动装配的,都可以放在属性字段上
    • @Autowired 通过byType的方式实现 ,如果找不到 名字,则通过byName实现
    • @Resource 默认通过byName的方式实现,如果找不到 名字,则通过byType实现!如果两个都找不到的情况下就报错,@Resource还可以通过直接给标记的属性指定值来让他找 指定的bean的id
    • 执行顺序不同:@Autowired 通过byType的方式实现,@Resource 先默认通过byName的方式实现

8、使用注解开发

在Spring4之后,要使用注解开发,必须要保证 aop 的包导入了

在这里插入图片描述

  • 使用注解需要导入context约束,增加注解的支持!

    <?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>
    
  1. bean

    //在类上面加一个 @Component 注解就相当于:<bean id="user" class="com.feng.pojo.User"/>
    //这里的 id 就是 这个类类名的小写
    @Component //英文是组件的意思
    public class User {
        
    }
    
  2. 属性如何注入

    //@Value("小明") 相当于:<property name="name" value="小明"/> 即给属性复制
    @Value("小明")  
    public String name ;
    @Value("小明")  //也可以放在set方法上
    public void setName(String name) {
            this.name = name;
    }
    
  3. 衍生的注解

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

    • dao 【@Repository】 dao层
    • service 【@service】 业务层
    • controller 【@controller】 servlet层

    这四个是等价的,功能是一样的,都是代表将某个类注册到Spring中,装配bean只是开发中层数的不同我们习惯上每层用不一样的注解。

  4. 自动装配:(即装配属性为自定义的引用类型 和 基本类型的属性是复制(用@Value(“小明”) )是不一样的

    • @Autowired: 通过byType的方式实现 ,如果找不到 名字,则通过byName实现
    • @Qualifier:如果 @Autowired 不能唯一自动装配上属性,则需要通过@Qualifier(value=“XXX”)
    • @Nullable:字段标记了这个注解,说明这个字段可以为null;
    • @Resource:默认通过byName的方式实现,如果找不到 名字,则通过byType实现!
  5. 作用域

    @Scope("prototype")//作用域设置为原型模式
    public class User {
    }
    
  6. 小结

    xml与注解:

    • xml 更加万能,适用于任何场合!维护简单方便
    • 注解不是自己类使用不了,维护相对复杂

    xml与注解最佳实现:

    • xml 用来管理bean;

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

    • 我们在使用的过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持。

          <!--开启注解支持-->
          <context:annotation-config/>
          <!--指定要扫描的包,在这个包下面的注解就会生效-->
          <context:component-scan base-package="com.feng.pojo"/>
      

9、使用Java的方式配置Spring

  • 我们现在要完全不使用Spring的xml配置了。全权交给java来做!
  • JavaConfig 是 Spring 的一个子项目,在Spring 4 之后,他成为了一个核心功能!

在这里插入图片描述

实体类:

package com.feng.pojo;

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

//这个注解的意思还是和原来一样,就是说明这个类被Spring接管了,注册到了容器中
@Component
public class User {
    //给name属性复制为小明
    @Value("小明")//属性注入值
    private String name;

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

    public String getName() {
        return name;
    }

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

配置类:

package com.feng.config;

import com.feng.pojo.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;

//@Configuration注解代表这是一个配置类,就和之前的beans.xml文件是一样的
@Configuration //这个也会被Spring容器托管,注册到容器中,因为他本来就是一个@Component
@ComponentScan("com.feng.pojo") //扫描包
@Import(UserConfig2.class) //将其他类的配置导入进来
public class UserConfig {

    //这里注册一个bean,就相当于我们之前写的一个bean标签
    //id 就是方法名  返回值就相当于bean标签中的class属性
    //<bean id="getUser" class="User"/>
    @Bean
    public User getUser(){
        return new User();//就是返回要注入到bean的对象
    }
}

测试类:

import com.feng.config.UserConfig;
import com.feng.pojo.User;
import org.junit.Test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyTest {
    @Test
    public void Test01(){
        //如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载
        ApplicationContext context = new AnnotationConfigApplicationContext(UserConfig.class);
        User user = context.getBean("getUser", User.class);
        System.out.println(user.getName());
        System.out.println(user.toString());
    }
}

这种纯Java的配置方式,在SpringBoot中随处可见!

10、代理模式

代理:代理就是帮一些人做一些事情。

为什么要学习代理模式? 因为这就是SpringAOP的底层!

面试:【SpringAOP 和 SpringMVC】必问!

代理模式的分类:

  • 静态代理
  • 动态代理

在这里插入图片描述

10.1、静态代理

角色分析:

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

    //住房这件事,作为一个接口
    public interface Rent {
        //租房的方法
        public void rent();
    }
    
  • 真实角色:被代理的角色

    //房东,要租房子 就要继承租房接口,实现租房方法
    public class Host implements Rent{
        @Override
        public void rent() {
            System.out.println("房东要出租房子!!");
        }
    }
    
    
  • 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作

    //中介,它要出租房东的房子,即他自己也要会出租房子
    //就要实现租房的接口,帮房东出租房子
    public class Proxy implements Rent{
        private Host host;
    
        //这里用set方法和构造方法都是一样的,都可以注入
        public void setHost(Host host) {
            this.host = host;
        }
    
        @Override
        public void rent() {//中介出租房子
            seeHose();
            host.rent();//本质还是房东出租房子
            hetong();
            fare();
        }
    
        //但中介还会做其它事情;
        //带你看房子
        public void seeHose(){
            System.out.println("中介带你看房子!");
        }
        //带你签合同
        public void hetong(){
            System.out.println("中介带你签合同!");
        }
        //收中介费
        public void fare(){
            System.out.println("收取中介费!");
        }
    }
    
  • 客户:访问代理对象的人!

    //需要租房的人,真实的人,,他要找房东租房子
    //但现在它找不到房东,他只能找到中介。
    public class Client {
        public static void main(String[] args) {
            //找中介
            Proxy proxy = new Proxy();
            //中介背地里联系房东
            Host host = new Host();
            proxy.setHost(host);
    
            //中介出租房子(执行出租房子的方法)
            proxy.rent();
        }
    }
    

代理模式的好处:

  • 可以使真实的角色的操作更加纯粹!不用去关注一些公共的它的业务,如:房东就只需要会出租房子,像签合同,看人房子,这些事情可以交给代理角色(中介)来做。
  • 这样就实现了业务的分工!
  • 公共业务发生扩展的时候,方便集中管理!

缺点:

  • 一个真实角色就会产生一个代理角色,代码量会翻倍开发效率会变低

10.2、加深理解

  • 假如在公司中你需要在写好的几层架构中间添加一个日志功能,还不要改变原来的代码,这是代理模式就是很好的实现机制,AOP的实现机制就是代理模式!

  • 接口UserService

    public interface UserService {
        void add();
        void update();
        void delete();
        void query();
    }
    
    
  • 真实的实现类UserServiceImpl

    package com.feng.demo02;
    
    public class UserServiceImpl implements UserService{
        @Override
        public void add() {
            System.out.println("增加了一个用户");
        }
    
        @Override
        public void update() {
            System.out.println("修改了一个用户");
    
        }
    
        @Override
        public void delete() {
            System.out.println("删除了一个用户");
    
        }
    
        @Override
        public void query() {
            System.out.println("查询了一个用户");
    
        }
    }
    
  • 代理实现类UserServiceProxy,想实现增加日志的功能

    package com.feng.demo02;
    
    //代理角色,代理真实角色
    public class UserServiceProxy implements UserService {
        private UserServiceImpl userServiceimpl;
    
        public void setUserServiceimpl(UserServiceImpl userServiceimpl) {
            this.userServiceimpl = userServiceimpl;
        }
    
        @Override
        public void add() {
            logj("add");
            System.out.println("增加了一个用户");
        }
    
        @Override
        public void update() {
            logj("update");
            System.out.println("修改了一个用户");
    
        }
    
        @Override
        public void delete() {
            logj("delete");
            System.out.println("删除了一个用户");
    
        }
    
        @Override
        public void query() {
            logj("query");
            System.out.println("查询了一个用户");
        }
    
        //业务中需要给每个方法上加上一个日志
        public void logj(String msg){
            System.out.println("这是一个"+msg+"方法");
        }
    }
    
  • 客户类Client

    package com.feng.demo02;
    
    public class Client {
        public static void main(String[] args) {
            //先找代理角色
            UserServiceProxy userServiceProxy = new UserServiceProxy();
            //代理角色找真实角色
            UserServiceImpl userService = new UserServiceImpl();
            userServiceProxy.setUserServiceimpl(userService);
    
            userServiceProxy.add();
    
        }
    }
    

    AOP的实现机制就是代理模式!

在这里插入图片描述

10.3、动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的!
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    • 基于接口—JDK动态代理【我们使用这个】
    • 基于类:cglig类
    • Java字节码实现:javasist

需要了解两个类:Proxy:代理,InvocationHandler:调用处理程序

核心类生成代理对象的类:

package com.feng.demo03;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//这个类不在是静态的一个代理类,而是会动态生成一个代理角色去代理真实角色
public class ProxyInvocationHandler implements InvocationHandler {

    //被代理的真实角色实现的接口
    //这里是租房
    private Rent rent;

    //使用set方法传入被代理的接口
    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //生成得到代理类(代理角色)
    public Object getProxy(){
        //这里要用到Proxy这个类来生成代理类
        //第一个参数为这个类的类加载器,
        //第二个参数为被代理对象实现的所有接口
        //第三个参数为这个类
        return Proxy.newProxyInstance(ProxyInvocationHandler.class.getClassLoader(),rent.getClass().getInterfaces(),this);
    }

    /*
    * 所有动态代理类的方法调用,都会交由invoke()方法去处理
    * proxy 被代理后的对象,即上面getProxy()方法生成的Object的对象
    *
    * */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHose();
        hetong();
        Object result = method.invoke(rent, args);
        fare();
        return result;
    }

    //但中介还会做其它事情;
    //带你看房子
    public void seeHose(){
        System.out.println("中介带你看房子!");
    }
    //带你签合同
    public void hetong(){
        System.out.println("中介带你签合同!");
    }
    //收中介费
    public void fare(){
        System.out.println("收取中介费!");
    }

}

测试:

package com.feng.demo03;


//需要租房的人,真实的人,,他要找房东租房子
//但现在它找不到房东,他只能找到中介。
public class Client {
    public static void main(String[] args) {
        //找中介 这时没有这个代理类,我们需要通过动态代理类来创建出来一个代理角色
        ProxyInvocationHandler handler = new ProxyInvocationHandler();
        //要去找被代理的真实角色 这里是房东
        Host host = new Host();
        //将真实角色注入到动态代理类中
        handler.setRent(host);

        Rent proxy = (Rent) handler.getProxy();//生成代理类
        proxy.rent();
    }
}

动态代理的好处:

  • 可以使真实的角色的操作更加纯粹!不用去关注一些公共的它的业务,如:房东就只需要会出租房子,像签合同,看人房子,这些事情可以交给代理角色(中介)来做。

  • 这样就实现了业务的分工!

  • 公共业务发生扩展的时候,方便集中管理!

  • 一个动态代理类代理的是一个接口,一般就是对应一类业务

  • 一个动态代理类可以代理多个类,只要是实现了同一个接口

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值