Spring简介
Spring核心
IOC容器: 控制反转, 把创建对象的过程交给Spring进行管理
AOP切面编程: 面向切面, 不修改源代码进行功能增强
Spring特点
- 方便解耦, 简化开发
- Aop编程支持
- 方便程序测试
- 方便和其他框架进行整合
- 方便进行事务操作
- 降低API开发难度
工厂模式解耦合过程
将代码中的耦合进行解耦, 放入到配置文件中. 当需要新增UserService的实现类时, 不需要对原有代码进行修改, 修改配置文件即可. 实现从改代码到改配置的解耦合.
Spring框架相当于提供了一个工厂ApplicationContext和一个配置文件applicationContext.xml
public class XBeanFactory {
// 耦合: 从测试代码(应用程序代码) -> 工厂方法中的代码
public static UserService getUserServiceV1() {
return new UserServiceImpl();
}
// 反射: 从工厂方法 -> 字符串硬编码
public static UserService getUserServiceV2() throws Exception {
Class<?> clazz = Class.forName("com.example.spring.service.UserServiceImpl");
return (UserService) clazz.getDeclaredConstructor().newInstance();
}
// 字符串硬编码 -> 配置文件
// 使用工具类从配置文件中获取信息
public static UserService getUserServiceV3() throws Exception {
Properties properties = new Properties();
properties.load(new BufferedReader(new InputStreamReader(new FileInputStream("G:/spring/src/main/resources/application.properties"))));
String serviceImplName = properties.getProperty("serviceImplName");
Class<?> clazz = Class.forName(serviceImplName);
return (UserService) clazz.getDeclaredConstructor().newInstance();
}
// 将properties设置为静态变量, 只需要加载配置文件一次
private static Properties properties = new Properties();
static {
try {
// 加载方式一
// properties.load(new BufferedReader(new InputStreamReader(new FileInputStream("G:/spring/src/main/resources/application.properties"))));
// 加载方式二
// 1. 为什么XBeanFactory.class不能替换为Object.class?
// 2. 为什么要使用/application.properties而不能使用application.properties
properties.load(XBeanFactory.class.getResourceAsStream("/application.properties"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static UserService getUserServiceV4() throws Exception {
String serviceImplName = properties.getProperty("serviceImplName");
Class<?> clazz = Class.forName(serviceImplName);
return (UserService) clazz.getDeclaredConstructor().newInstance();
}
// 对配置参数进行解耦合
public static UserService getUserServiceV5() throws Exception {
String serviceImplName = properties.getProperty(UserServiceConstant.userServiceImplName);
Class<?> clazz = Class.forName(serviceImplName);
return (UserService) clazz.getDeclaredConstructor().newInstance();
}
// 每个getXXX的结构都是相同的, 所以为每一个对象都创建一个工厂是没有意义的, 会出现大量的冗余代码, 例如Properties.load(...)等
// 因此需要通用工厂, 提供一个方法, 创建想要的不同类型的对象
// 设计通用方法需要考虑方法声明的5个要素:
// 1. 修饰符 public static
// 2. 返回值类型 UserDao
// 3. 方法名 getUserDao
// 4. 参数列表 ()
// 5. 可选项: 异常
public static UserDao getUserDao() throws Exception {
String daoImplName = properties.getProperty("daoImplName");
Class<?> clazz = Class.forName(daoImplName);
return (UserDao) clazz.getDeclaredConstructor().newInstance();
}
// 通用方法的设计
public static Object getBean(String key) throws Exception {
String value = properties.getProperty(key);
Class<?> clazz = Class.forName(value);
return clazz.getDeclaredConstructor().newInstance();
}
// 提供泛型, 减少每次调用都要手动进行强转
public static <T> T getBean(String key, Class<T> tClass) throws Exception {
return (T) getBean(key);
}
}
public class Application {
public static void main(String[] args) throws Exception {
// 这里不使用new UserServiceImpl()的方式来获取UserService对象, 而是使用工厂模式来创建对象
UserService userService = XBeanFactory.getUserServiceV4();
String result = userService.register("root");
System.out.println(result);
}
}
代理模式
JavaEE分层开发中,Service层对应用户的需求,因此是最重要最核心的部分。