Spring代理(Proxy)设计模式

Spring代理设计模式

1.为什么需要代理设计模式

1.1问题

我们在写一个程序时,会创建Service层,在这里主要实现关键代码:业务运算+DAO调用

但有时候我们也想在Service层中加入一些简单的额外方法,可这些额外方法日后会随着需求一点点改变的,

这样大部分Service中的代码有额外功能这种多余的代码,就会影响维护性。所以需要引入------代理模式

2.代理设计模式

好处:利于目标类和原始类的维护。

步骤:

  • 先定义个接口,让原始类 和 代理类共同实现它
  • 原理类实现接口,在Override中,将核心部分写入。-这就是我们最关键的Service层
  • 代理类实现接口,他是可以实现核心方法+额外方法的类。在Override中,将原始类实例化,调用原始类方法来实现核心方法,然后加入额外方法来实现额外方法。

Step 1定义个接口

public interface UserService {
    void register(User user);
    void login(String name,String password);
}

Step 2原始类实现接口

public class UserServiceImpl implements UserService{
    @Override
    public void register(User user) {
        System.out.println("UserServiceImpl.register 业务运算 + DAO");
    }

    @Override
    public void login(String name, String password) {
        System.out.println("UserServiceImpl.login 业务运算 + DAO");
    }
}

Step 3代理类实现接口(核心方法+额外方法)

public class UserServiceProxy implements UserService{
    UserService userService = new UserServiceImpl();

    @Override
    public void register(User user) {
        System.out.println("这里是代理+额外方法");
        userService.register(user);
    }

    @Override
    public void login(String name, String password) {
        System.out.println("这里是代理+额外方法");
        userService.login(name,password);
    }
}

Step 4测试

public void test1(){
        UserService userService = new UserServiceProxy();
        userService.login("name","123456");
        System.out.println("===================");
        userService.register(new User());
    }

3.Spring动态代理开发

概念:通过使用Spring框架中的代理类来为原始类增加额外功能

好处:利于原始类的维护

Step 1POM导入依赖

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>5.1.14.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjrt</artifactId>
  <version>1.8.9</version>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.8.13</version>
</dependency>

Step 2创建接口+原始对象

public interface UserService {
    void register(User user);
    boolean login(String name, String password);
}
public class UserServiceImpl implements UserService {
    @Override
    public void register(User user) {
        System.out.println("UserServiceImpl.register 业务运算 + DAO");
    }

    @Override
    public boolean login(String name, String password) {
        System.out.println("UserServiceImpl.login 业务运算 + DAO");
        return true;
    }
}

Step 3实现额外功能接口

MethodBeforeAdvice接口+XML文件实例化

public class Before implements MethodBeforeAdvice {
    /**
     * 作用: 把需要运行在原始方法执行之前运行的额外功能, 书写在 before 方法中
     */
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("---method before advice log---");
    }
}

👇在XML文件中配置

<!-- 额外功能 -->
<bean id="before" class="com.yusael.aop.Before"/>

Step 4额外功能加入位置

  1. 定义 切入点:额外功能的加入
    目的: 由程序员根据自己的需要,决定额外功能加入给哪个原始方法(register、login)
 <!--切入点:额外功能的加入-->
    <!--目的: 由程序员根据自己的需要,决定额外功能加入给哪个原始方法(register、login)-->
   <!-- 简单的测试:所有方法都做为切入点,都加入额外的功能-->
    <aop:config>
        <aop:pointcut id="pc" expression="execution(* * (..))"/>
    </aop:config>

Step 5位置和额外功能映射

<aop:advisor advice-ref="before" pointcut-ref="pc"/>

  <bean id="userService" class="com.yusael.aop.UserServiceImpl"/>

    <!-- 额外功能 👇-->
    <bean id="before" class="com.yusael.aop.Before"/>

    <!--切入点:额外功能的加入-->
    <!--目的:由程序员根据自己的需要,决定额外功能加入给哪个原始方法(register、login)-->
   <!-- 简单的测试:所有方法都做为切入点,都加入额外的功能-->
    <aop:config>
        <!--定义切入点ID 和切入点位置 execution(* * (..))=全部方法 👇-->
        <aop:pointcut id="pc" expression="execution(* * (..))"/>
        <!--表达的含义: 所有的方法 都加入before的额外功能-->
        <aop:advisor advice-ref="before" pointcut-ref="pc"/>
    </aop:config>

</beans>

Step 5测试

ctx.getBean("userService");里的id,在xml文件中是原始类,

/**
 * 用于测试动态代理
 */
@Test
public void test1() {
    ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
    UserService userService = (UserService) ctx.getBean("userService");
    userService.login("admin", "1234");
    userService.register(new User());
}

4.MethodBeforeAdvice

MethodBeforeAdvice是动态代理的接口类,我们在使用框架中的动态代理时需要对其实现。

接下来我们会对MethodBeforeAdvice中的三个参数进行解析

before(Method method, Object[] objects, Object o)

public class Before implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("---method before advice log---");
    }
}
  • Method method:需要增加额外功能的那个 原始方法

    比如:login()register()

  • Object[] objects:需要增加额外功能的那个 原始方法的形参

    比如:login()中的,String name,String password

    register()中的,User user

  • Object o:需要增加额外功能的那个 原始对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring 使用了多种设计模式,常见的设计模式包括: 1. 单例模式(Singleton Pattern):Spring 的核心容器 ApplicationContext 都是单例对象,保证了容器中的 Bean 对象也是单例的。 2. 工厂模式(Factory Pattern):Spring 使用工厂模式创建和管理 Bean 对象,通过配置文件或注解来实现对 Bean 的创建和配置。 3. 代理模式(Proxy Pattern):Spring AOP(面向切面编程)使用代理模式来实现横切关注点的功能,如事务管理、日志记录等。 4. 观察者模式(Observer Pattern):Spring 的事件驱动机制基于观察者模式,通过监听器(Listener)来处理事件。 5. 模板模式(Template Pattern):Spring 的 JdbcTemplate 使用了模板模式,将数据库操作的公共部分封装在模板中,减少了重复代码的编写。 6. 建造者模式(Builder Pattern):Spring 的构建者模式用于配置复杂的对象,如 BeanDefinitionBuilder 用于构建 BeanDefinition 对象。 7. 适配器模式(Adapter Pattern):Spring 的适配器模式用于将不同的接口适配到统一的接口,如 HandlerAdapter 用于处理不同类型的请求处理器。 8. 装饰器模式(Decorator Pattern):Spring 的装饰器模式用于增强现有对象的功能,如 AOP 中的切面(Aspect)就是通过装饰器模式实现的。 以上只是一些常见的设计模式Spring 中的应用,实际上 Spring使用了其他设计模式来提供更强大的功能和灵活性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值