Spring5深入浅出篇:Spring工厂设计模式拓展应用

简介: Spring5深入浅出篇:Spring工厂设计模式拓展应用

Spring5深入浅出篇:Spring工厂设计模式拓展应用

简单工厂实现

这里直接上代码举例子

UserService.java

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

UserServiceImpl.java

public class UserServiceImpl implements UserService {
    private UserDAO userDAO = new UserDAOImpl();
    public UserDAO getUserDAO() {
        return userDAO;
    }
    public void setUserDAO(UserDAO userDAO) {
        this.userDAO = userDAO;
    }
    @Override
    public void register(User user) {
        userDAO.save(user);
    }
    @Override
    public void login(String name, String password) {
        userDAO.queryUserByNameAndPassword(name, password);
    }
}

UserDAOImpl.java

public class UserDAOImpl implements UserDAO {
    @Override
    public void save(User user) {
        System.out.println("insert into user = " + user);
    }
    @Override
    public void queryUserByNameAndPassword(String name, String password) {
        System.out.println("query User name = " + name+" password = "+password);
    }
}

为了方便测试更直观看到结果UserDAOImpl的方法采用打印一条字符串来体现,下面就通过测试类来调用UserService

测试类

/**
     *  用于测试:工厂类进行解耦合的操作
     */
    @Test
    public void test1() {
       UserService userService = new UserServiceImpl();
        UserService userService = (UserService) BeanFactory.getBean("userService");
        userService.login("name", "suns");
        User user = new User("suns", "123456");
        userService.register(user);
    }

最终结果如下:

可以发现当我们在上图中就出现了耦合,当我们需要重新换一个实现类的时候需要重新修改代码在进行编译部署.下面就通过工厂设计模式来解决这个问题.

创建工厂类

BeanFactory.java

public class BeanFactory {
       public static UserService getUserService(){
    return new UserServiceImpl();
    }
}

这样就通过了工厂类中提供的getUserService方法来获取对象,这样测试类中就彻底没有耦合了,但是new对象的方法写到了工厂类中,下面来看看如何解决.

对象的创建方式

  • 直接调用构造方法 创建对象
UserService userService = new UserServiceImpl();
  • 通过反射的形式 创建对象 解耦合
Class clazz = Class.forName("com.baizhiedu.basic.UserServiceImpl");
UserService userService = (UserService)clazz.newInstance();

重新修改工厂类

BeanFactory.java

public class BeanFactory {
       public static UserService getUserService(){
     UserService userService = null;
        try {                        
            Class clazz = Class.forName("com.baizhiedu.basic.UserServiceImpl");
            userService = (UserService) clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return userService;
    }
}

通过反射并不能完全解决耦合的问题,因为这里的全限定类名字符串如果需要修改,也涉及到需要修改源码.这里我们通过读取resources下的properties文件来进行优化

applicationContext.properties

userService = com.baizhiedu.basic.UserServiceImpl

BeanFactory.java

private static Properties env = new Properties();
    static{
        try {
            //第一步 获得IO输入流
            InputStream inputStream = BeanFactory.class.getResourceAsStream("/applicationContext.properties");
            //第二步 文件内容 封装 Properties集合中 key = userService value = com.baizhixx.UserServiceImpl
            env.load(inputStream);
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
public static UserService getUserService() {
        UserService userService = null;
        try {
                                         //com.baizhiedu.basic.UserServiceImpl
            Class clazz = Class.forName(env.getProperty("userService"));
            userService = (UserService) clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return userService;
    }

这里就是直接通过配置文件读取对应的全限定类名即可,使我们程序之间的耦合解决.即便是我们还需要解决UserDaoImpl的耦合也是异曲同工,只需要将UserServiceImpl,改成UserDaoImpl

UserDAO解耦

BeanFactory.java

public static UserDAO getUserDAO(){
        UserDAO userDAO = null;
        try {
            Class clazz = Class.forName(env.getProperty("userDAO"));
            userDAO = (UserDAO) clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return userDAO;
    }

applicationContext.xml

<bean id="userDAO" class="com.baizhiedu.basic.UserDAOImpl"></bean>

通用工厂实现


可以发现上图代码出现冗余,我们应该对这种重复的代码块进行抽取

通用工厂代码

public class BeanFactory{
 public static Object getBean(String key){
    Object ret = null;
 try {
    Class clazz = Class.forName(env.getProperty(key));
    ret = clazz.newInstance();
 } catch (Exception e) {
  e.printStackTrace();
 }
    return ret;
 }
}

这样只需要在applicationContext.xml中增加对应配置,就可以通过getBean方法传入对应的key从工厂获取到对象了.

@Test
    public void test1() {
        UserService userService = (UserService) BeanFactory.getBean("userService");
        userService.login("name", "suns");
        User user = new User("suns", "123456");
        userService.register(user);
    }

通用工厂的使用方式

1.定义类型(需要创建对象的类)

2.通过配置文件的配置告知工厂(applicationContext.properties)

以key = value的形式

3.通过工厂获得类的对象

Object ret = BeanFactory.getBean("key")

总结

Spring的本质其实就是工厂+配置文件的形式,但是Spring提供的工厂肯定是比我们现在设计的工厂功能要更加强大.

相关文章
|
4月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
857 3
|
3月前
|
SQL Java 数据库连接
Spring Data JPA 技术深度解析与应用指南
本文档全面介绍 Spring Data JPA 的核心概念、技术原理和实际应用。作为 Spring 生态系统中数据访问层的关键组件,Spring Data JPA 极大简化了 Java 持久层开发。本文将深入探讨其架构设计、核心接口、查询派生机制、事务管理以及与 Spring 框架的集成方式,并通过实际示例展示如何高效地使用这一技术。本文档约1500字,适合有一定 Spring 和 JPA 基础的开发者阅读。
425 0
|
2月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
154 8
|
4月前
|
Java 应用服务中间件 开发者
Spring Boot 技术详解与应用实践
本文档旨在全面介绍 Spring Boot 这一广泛应用于现代企业级应用开发的框架。内容将涵盖 Spring Boot 的核心概念、核心特性、项目自动生成与结构解析、基础功能实现(如 RESTful API、数据访问)、配置管理以及最终的构建与部署。通过本文档,读者将能够理解 Spring Boot 如何简化 Spring 应用的初始搭建和开发过程,并掌握其基本使用方法。
386 2
|
4月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
4月前
|
安全 算法 Java
在Spring Boot中应用Jasypt以加密配置信息。
通过以上步骤,可以在Spring Boot应用中有效地利用Jasypt对配置信息进行加密,这样即使配置文件被泄露,其中的敏感信息也不会直接暴露给攻击者。这是一种在不牺牲操作复杂度的情况下提升应用安全性的简便方法。
1079 10
|
5月前
|
安全 Java Nacos
0代码改动实现Spring应用数据库帐密自动轮转
Nacos作为国内被广泛使用的配置中心,已经成为应用侧的基础设施产品,近年来安全问题被更多关注,这是中国国内软件行业逐渐迈向成熟的标志,也是必经之路,Nacos提供配置加密存储-运行时轮转的核心安全能力,将在应用安全领域承担更多职责。
|
设计模式 Java 数据库连接
Spring中涉及的设计模式,速度保存起来(下)
Spring中涉及的设计模式,速度保存起来
168 0
|
5月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
993 0
|
6月前
|
人工智能 Java 测试技术
Spring Boot 集成 JUnit 单元测试
本文介绍了在Spring Boot中使用JUnit 5进行单元测试的常用方法与技巧,包括添加依赖、编写测试类、使用@SpringBootTest参数、自动装配测试模块(如JSON、MVC、WebFlux、JDBC等),以及@MockBean和@SpyBean的应用。内容实用,适合Java开发者参考学习。
745 0