文章目录
一、三层架构的改进
1.三层架构概述
概述:
三层架构是指:视图层、业务层、持久层的三层架构开发方式;
优点:
1.结构清晰,分工明确
2.便于团队开发,提高效率
使用案例:
持久层:
//接口
public interface UserDao {
int save(User user);
}
//实现类
public class UserDaoImpl implements UserDao {
@Override
public int save(User user) {
System.out.println("保存成功!");
return 1;
}
}
业务层:
//接口
public interface UserService {
int register(User user);
}
//实现类
public class UserServiceImpl implements UserService {
//创建持久层实例对象
private UserDao userDao = new UserDaoImpl();
@Override
public int register(User user) {
//直接返回结果给视图层
return userDao.save(user);
}
}
视图层:
public class UserServlet {
//创建业务层实例对象
private static UserService userService = new UserServiceImpl();
public static void register() {
//简单演示,就不放数值了
User user = new User();
//调用方法
int i = userService.register(user);
if (i == 1) {
System.out.println("注册成功");
} else {
System.out.println("注册失败");
}
}
public static void main(String[] args) {
//调用方法
UserServlet.register();
}
}
运行结果:
存在的问题:
代码耦合度太高
耦合度太高有什么影响?
1.当实现类丢失的时候会发生编译问题导致项目死亡
2.在切换实现类的时候,需要修改代码
2.改进方式
祸水东引:
public class BeanFactory {
//即使用工具类来创建实现类,这样就不会影响到主题代码
//但是这样的基本工厂模式无法真正意义上解决问题
public static UserDao getBean(){
return new UserDaoImpl();
}
}
动态加载:
//利用反射机制加载配置文件中的信息
//这样的话,就只需要在配置文件中修改配置信息
public class DaoObject {
//创建配置文件
private static Properties properties = new Properties();
static {
try {
//读取配置文件中的信息
InputStream in = DaoObject.class.getResourceAsStream("/bean.properties");
//把信息读取到properties集合中
properties.load(in);
} catch (IOException e) {
e.printStackTrace();
}
}
public static <T> T getInstance(Class<T> className) {
try {
//1.判断传入的类是否为接口
//因为只有接口才需要帮助创建具体的实现类,也就是需要面向接口开发
if (className.isInterface()) {
//2.从配置文件中读取要实现的类全名字符串
String newName = properties.getProperty(className.getSimpleName());
//3.通过类全名字符串获取class对象
Class newClass = Class.forName(newName);
//4.返回对应的对象
return (T) newClass.newInstance();
}
} catch (Exception e) {
return null;
}
return null;
}
}
配置文件内容:
user=com.ps.pojo.impl.userImpl
3.工厂模式
概述:
工厂模式在开发中被广泛使用,主要目的就是降低代码的耦合度,通过第三方工厂来实现功能
作用:
1.创建对象
2.降低耦合度
3.消除重复
二、Spring框架概述
官网地址:
- 官网: https://spring.io/
-
官网文档地址: https://spring.io/projects/spring-framework#learn
-
依赖下载地址: https://repo.spring.io/libs-release-local/org/springframework/spring/
框架简介:
-
Spring是 分层 的轻量级开源框架 (重点)
-
Spring核心是IOC(控制反转) 和 AOP(面向切面编程)
-
Spring提供了对各种优秀框架的支持和 整合
-
Spring框架采用分层架构, 根据不同的功能被划分成了多个模块,结构清晰。
框架的优点:
1.IOC解耦合
2.支持AOP面向切面编程思想
3.声明式事务,可以仅仅通过配置或注解的方式管理事务
4.便于测试
5.方便继承
6.使用简单
7.设计巧妙精良,是良好的Java学习代码
三、IOC控制反转
1.概述
概述:
英文名称:IOC(Inversion Of Control)
中文名称:反转控制
什么是IOC:
将对象的创建(控制)交给第三方工厂完成被称为IOC(即反转控制);
IOC的作用:
1.解耦,降低代码之间的耦合度
2.存储对象,把对象存储起来重复使用(可以参考单例模式)
3.管理依赖关系,将依赖对象注入到需要的对象中
4.管理对象创建顺序,根据依赖关系先后创建对象
要使用的依赖:
<!--spring IOC依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
2.入门案例
实体类:
public class User {
private int id;
private String username;
private Date birthday;
private String sex;
private String address;
public void init() {
System.out.println("初始化方法");
}
public void destroy() {
System.out.println("销毁方法");
}
public User() {
System.out.println("无参构造方法");
}
public User(int id, String username, Date birthday, String sex, String address) {
this.id = id;
this.username = username;
this.birthday = birthday;
this.sex = sex;
this.address = address;
}
public User(int id, String username) {
this.id = id;
this.username = username;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
测试代码:
@Test
public void testUserCreate() {
//创建IOC容器,即IOC工厂,字符串就是配置文件的路径
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
//利用IOC创建对象,并获得对象
User user = (User)context.getBean("user");
System.out.println(user.getClass());
//关闭IOC容器
context.close();
}
配置文件:
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--bean要帮助创建的实体类-->
<!--
id:这个类的唯一标识,给对象起的名字,用来从IOC中获取对象
class:要创建的实体类的类全名字符串
-->
<bean id="user" class="com.ps.pojo.User"></bean>
</beans>
测试结果:
3.Bean标签的使用
常用属性:
属性 | 说明 |
---|---|
id | 对象的引用名称;一定要唯一; 一次只能定义一个引用名称 |
name | 对象的引用名称; 与id区别是:name一次可以定义多个引用名称。 |
class | 类全名字符串 |
destroy-method | 指定类中销毁方法名称,在销毁spring容器前执行 |
init-method | 指定类中初始化方法的名称,在构造方法执行完毕后立即执行 |
lazy-init | 设置为true表示在第一次使用对象的时候才创建,只对单例对象有效。 |
使用案例:
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--bean要帮助创建的实体类-->
<!--
id:这个类的唯一标识,给对象起的名字,用来从IOC中获取对象
name:给对象设置的别名,可以有多个,使用逗号或者空格分隔,在整个容器中也不能重复
上面这两个属性也可以没有,如果没有的话需要使用类名.class来获取类对象
init-method:创建容器的时候要调用的初始化方法,写方法名即可
destroy-method:销毁容器时候执行的方法,写方法名即可
class:要创建的实体类的类全名字符串
-->
<!--bean对象的作用范围属性
lazy-init:设置是否延迟创建对象,只对单例对象有效
true:第一次使用的时候才创建,即第一次获得对象的时候
false:容器创建的时候创建类对象
scope:设置bean的作用范围;
singleton:即设置为单例,默认值;
prototype:多例,设置之后,获得的对象不会放到容器中,所以容器关闭的时候,不会触发对象的销毁方法
-->
<bean scope="prototype" lazy-init="true"
init-method="init" destroy-method="destroy"
id="user" class="com.ps.pojo.User"></bean>
</beans>
测试代码:
@Test
public void testUserCreate() {
//创建IOC容器,即IOC工厂,字符串就是配置文件的路径
//这个代码不会调用user的销毁方法,因为我配置的并不是单例模式
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
//从IOC创建对象,并获得对象
User user = (User) context.getBean("user");
System.out.println(user.getClass());
context.close();
}
测试结果:
4.Bean对象的作用范围
属性 | 说明 |
---|---|
scope | 设置bean的作用范围, 取值: singleton:单例, 默认值; prototype:多例 request:web项目中,将对象存入request域中 session:web项目中,将对象存入session域中 globalsession:web项目中,将对象应用于集群环境,没有集群相当于session |
测试代码同上;
5.IOC容器的创建方式
资源文件创建方式:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
系统文件创建方式:
//这里可以使用绝对路径也可以使用相对路径,但是最好使用相对路径(这个相对路径是相对于整个项目的路径,而不是以往的src或者java之类的)
//如果要在这里使用绝对路径,那么只能使用windows系统,因为这个的绝对路径判断需要使用盘符开头才行,不然容易读取不到
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("applicationContext.xml");
注解方式:
创建第三方配置类:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class demo {
@Bean
public User getUser() {
return new User();
}
}
创建方式:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(demo.class);
BeanFactory创建
Resource resource = new ClassPathResource("beans.xml");
XmlBeanFactory context = new XmlBeanFactory(resource);
BeanFactory与ApplicationContext的区别?
- BeanFactory是Spring容器的顶层接口, 采用 延迟创建 对象的思想
- ApplicationContext是BeanFactory的子接口, 采用 即时创建 对象的思想
6.Bean对象的创建方式
通过构造方法:(默认方式)
<!-- 调用构造方法创建对象 -->
<bean id="user" class="com.ps.pojo.User"/>
通过静态方法:(调用工具类静态方法)
//工具类
public class UserUtil {
public User newUser() {
return new User();
}
}
<!-- 调用静态方法创建对象 -->
<bean id="user" class="com.ps.utils.UserUtil" factory-method="create"/>
通过实例方法:(调用对象的实例方法)
//工具类
public class UserUtil {
public static User getUser() {
return new User();
}
}
<!-- 调用动态方法创建对象 -->
<bean id="UserUtil" class="com.ps.utils.UserUtil"/>
<bean id="user" factory-bean="userFactory" factory-method="get"/>
四、依赖注入
简介:
依赖注入简称DI(dependency injection),是IOC容器提供的一种给对象成员变量赋值的功能
1.依赖注入的两种方式
注入的两种方式:
1.通过对象的构造方法注入
2.通过对象的setter方法注入
通过对象的构造方法:
<!--constructor-arg标签的作用:给构造方法传递参数
index:参数的索引,默认从0开始
name:参数的名字
value:参数的值
-->
<!--注意:这里要满足构造方法的所有参数,不然会报错-->
<bean id="user10" class="com.ps.pojo.User">
<constructor-arg name="id" value="100"></constructor-arg>
<constructor-arg name="username" value="123456"></constructor-arg>
</bean>
通过对象的setter方法
<!--使用set方法给对象的成员变量赋值-->
<bean id="user11" class="com.ps.pojo.User">
<property name="username" value="hahaha"></property>
<property name="id" value="001"></property>
</bean>
C标签注入
<!--通过C标签给成员变量赋值,要记得导入标签,不然会报错-->
<bean id="user12" class="com.ps.pojo.User" c:id="1" c:username="123456"></bean>
P标签注入:
<!--通过P标签给成员变量赋值,要记得导入标签,不然会报错-->
<bean id="user13" class="com.ps.pojo.User" p:id="2" p:sex="nan" p:username="ntt"></bean>
2.注入对象
<!--通过ref引用已经存在的对象-->
<bean id="str" class="java.lang.String">
<constructor-arg value="ohuo"></constructor-arg>
</bean>
<!--通过ref引入上面的字符串-->
<bean id="user14" class="com.ps.pojo.User">
<property name="id" value="109"></property>
<property name="username" ref="str"></property>
</bean>
3.注入集合
实体类
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class Employee {
private String[] array;
private Set<String> set;
private List<String> list;
private Map<String, String> map;
private Properties properties;
public String[] getArray() {
return array;
}
public void setArray(String[] array) {
this.array = array;
}
public Set<String> getSet() {
return set;
}
public void setSet(Set<String> set) {
this.set = set;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
}
配置代码
<bean class="com.ps.pojo.Employee" id="employee">
<property name="array">
<array>
<value>1</value>
<value>11</value>
<value>111</value>
<value>1111</value>
</array>
</property>
<property name="list">
<list>
<value>1</value>
<value>11</value>
<value>111</value>
<value>1111</value>
</list>
</property>
<property name="properties">
<props>
<prop key="name">hahaha</prop>
</props>
</property>
<property name="map">
<map>
<entry key="1" value="2"></entry>
</map>
</property>
<property name="set">
<set>
<value>1</value>
<value>11</value>
<value>111</value>
<value>1111</value>
</set>
</property>
</bean>
总结:
1.需要通过proterty属性配置
2.需要拆分到不可拆分为止
3.语法相近
类型 | 格式 |
---|---|
数组 | <array> <value> 具体的值</value> … </array> |
List集合 | <list> <value> 具体的值</value> … </list> |
Set集合 | <set> <value> 具体的值</value> … </set> |
Map集合 | <map> <entry key="键" value="值">``</entry> … </map> |
properties集合 | <props> <prop key="键"> 值</prop> … </props> |