Spring工厂模式实现

本文深入探讨了Java反射机制,它是Spring工厂模式的基础。通过实例展示了如何使用工厂模式创建对象,特别是Spring中的Bean工厂。文章通过一个完整的通用工厂示例,解释了Service接口实现类如何通过工厂和反射加载 Dao 层接口实现类。同时,还提供了配置文件读取和对象创建的过程,以及测试类的运行结果。强调学习技术的目的在于实际应用。
摘要由CSDN通过智能技术生成

Spring工厂模式实现

工厂模式是一种在工程中广泛应用的设计模式,对代码的解耦合起到了很大的作用。在Spring使用开发中,我们可以将Spring理解成封装了我们工程中大量重复代码的一种工具,Spring中最为重要的组件就是IOC,而IOC中非常重要的部分就是应用了工厂模式的代码。而工厂模式依赖于Java的反射机制,所以,我们从反射机制讲起,一步步了解Spring的Bean工厂。

反射机制

什么是反射:

(1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。

(2)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

(3)在框架的底层使用非常多的设计模式,算法,还有反射等,我们可以通过反射去创建对象,简单点说,在学习面向对象的所有操作几乎都可以使用反射进行实现,下面来看个最常见的通过反射创建对象。

Class.forName("com.mysql.jdbc.Driver");
//数据库加载驱动可能就是我们学习反射之后,第一个写的连接数据库的工具类,我们还可以通过反射做其他操作newInstance()创建实例
//getClassLoader() 获取类加载器等

工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

实例

我们本次创建的是一个完整的通用工厂实例
实体类

package demo;

public class User {

	private String username;
	private String password;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	@Override
	public String toString() {
		return "User [username=" + username + ", password=" + password + "]";
	}
	
}

Dao层接口

package demo.dao;

import demo.User;

public interface UserDao {
	public void login();
	public User regeister(User user);
}

Dao层接口实现类

package demo.dao;

import demo.User;

public class UserDaoImpl implements UserDao{
	public void login() {
		System.out.println("login----UserDaoImpl");
	}
	public User regeister(User user) {
		return user;
	}
}

Service接口

package demo.Service;

import demo.User;

public interface UserService {

	public void login();
	public User regeister(User user);
}

Service接口实现类

package demo.Service;

import demo.User;
import demo.Factory.UserFactory;
import demo.dao.UserDao;

public class UserServiceImpl implements UserService {
	private UserDao userDao = (UserDao)UserFactory.getUserServiceImpl("userDao");
	/*这里就是通过我们写的工厂,通过反射进行对象的创建,接收的是一个
	字符串类型的值,该值就是读取的配置文件中的key

*/
	public void login() {
		userDao.login();
	}
	public User regeister(User user) {
		return userDao.regeister(user);
	}

}

properties配置文件

userService=demo.Service.UserServiceImpl
userDao=demo.dao.UserDaoImpl
#以key=value的形式 可以用等号分割也可以用空格进行分割key value
#这里的两个value都是对应类的绝对路径

BeanFactory工厂 —通用工厂用来通过反射进行对象的创建

package demo.Factory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import demo.Service.UserService;
import demo.Service.UserServiceImpl;

public class BeanFactory {
	public static Properties env = new Properties();
	  //这里使用的时静态方法读取的routes.properties配置文件
	static {
		InputStream inputStream =null;
	    try {
			 inputStream = BeanFactory.class.getResourceAsStream("/routes.properties");
			 env.load(inputStream);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if(inputStream!=null) {
				try {
				//在finally中关闭输入流
					inputStream.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	public static Object getUserServiceImpl(String routes) {
		Object rel =null;
		try{
            Class clazz = Class.forName(env.getProperty(routes));
            rel = clazz.newInstance();
        }catch(Exception e){
            e.printStackTrace();
        }
		return rel;
	}

}

所用到的方法
相信第一次看的时候会对这写方法有些疑问,毕竟这些都是在java之初就学习的,顺便复习一下

1.  inputStream = BeanFactory.class.getResourceAsStream("/routes.properties");
Object.class.getResourceAsStream()方法
如果写一个类需要动态的获取某个文件的位置,从而能够获取此文件的资源。那么,使用class.getResourceAsStream()方法便可以。
这样就不用每次去修改代码中文件的绝对地址或详细地址了。
2. env.load(inputStream)
load(InputStream)方法就是逐行读取properties配置文件,分隔成两个字符串key和value,将他们放进Properties对象中。
3.env.getProperty(routes)
getProperty(String key)获取配置文件中对应key的value值
**测试类**
package demo.Test;

import demo.User;
import demo.Factory.UserFactory;
import demo.Service.UserService;
import demo.Service.UserServiceImpl;

public class UsetTest {
  
	public static void main(String[] args) {
		String routes = "userService"; //配置文件中的key
		UserService userService =(UserService)UserFactory.getUserServiceImpl(routes);
		userService.login();
		User user = new User();
		user.setUsername("admin");
		user.setPassword("123456");
		System.out.println(userService.regeister(user));
		
	}
}

运行结果
测试结果
其他内容
学习不是即学即用,而是用的时候已经掌握。
Java学习之初疑问
Markdown基本语法
MySQL设置级联操作

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

离落&恠咖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值