2024/05/15
IOC将创建对象的权力反转给spring框架,降低了程序的耦合度
Java基础中,一个对象的创建只能是交给反射,因此,IOC底层使用反射。通过反射能做到解耦,(同理于我们定义变量,这个变量的值我们可能会在很多地方使用,但如果我们用的变量名,变量名就像占位符一样,以后变量名的值到底是什么,可以动态的赋值,即真正的变量的值与我们所使用的代码的耦合度降低了,相互间的影响降低了)。ioc使用反射,在运行时确定类型并创建对象,通过反射指定模板,不用写死某个东西,可以通过以后传参的方式将内容传递过去,动态的向模板中传入要实例化的对象。最大限度发挥了Java的灵活性,体现了多态的应用,有利于降低类之间的耦合度
Spring的IOC容器为什么用反射而不用new来创建实例
见博文:http://t.csdnimg.cn/M7sFJ
使用Junit测试的@Test注解的好处:
可以在一个类中进行不同的单元测试(相当于在一个类中有了很多个不同的main方法),可以避免经常编写测试类
ApplicationContext 中有哪两个类,这两个类有什么区别
ApplicationContext接口,是工厂接口,使用该接口可以获取到具体的bean对象,该接口下有两个具体的实现类
- ClassPathXmlApplicationContext,加载类路径下的spring配置文件(常用)
- FileSystemXmlApplicationContext,加载本地磁盘下的spring配置文件(让配置文件与项目分离管理,不常用)
bean管理的相关属性
- id属性:给bean起的名字,唯一性,
- id取值要求:必须以字母开始,可以用字母,数字,连字符、下划线,不能出现特殊字符
- class属性:bean对象的全路径
- scop属性:bean对象的作用范围
- singleton 单例(默认) 最常用的方式,生命周期跟配置文件一样,一加载配置文件,实例就创建
- prototype 多例 不常用 不是加载配置文件的时候创建实例,而是获取实例时,才创建实例
- request 多例 不常用 应用在web项目中,每次http请求都会创建一个新的实例
- session 多例 不常用 应用在web项目中,同一个http session共享一个实例
- init-method:bean对象创建时可以配置一个方法并自动调用
- destory-method:bean对象销毁时可以配置一个指定方法并自动调用
bean的scope的单例和多例生命周期相关理解:
业务层构造方法
仅创建动态工厂:
实例化对象的三种方式
-
默认是无参构造方法(默认方法,基本上都是用这种)
IOC底层反射默认调用无参构造方法,创建实例的时候必须显式的写出无参构造方法
-
静态工厂实例化方式(好处是可以自己编写业务逻辑)
-
实例化工厂(动态工厂)实例化方法(好处是可以自己编写业务逻辑)
2024/05/16
DI注入
Dependency Injection 依赖注入
在spring框架负责创建bean对象时,动态地将依赖对象注入到其他bean对象中,即给对象赋值,本质就是等号赋值
依赖注入的方式
1.属性set方法注入值
property标签的使用
- 简单类型(基本类型+字符串) property标签使用value属性赋值;
- 自定义引用类型 property标签使用ref属性赋值
2.属性的构造方法注入值
既要写有参构造器,也要写无参构造器
constructor-arg标签的使用
- 简单类型(基本类型+字符串) constructor-arg标签使用value属性赋值;
- 自定义引用类型 constructor-arg标签使用ref属性赋值
下述报错原因:只写了有参构造方法,没有写无参构造方法
3.数组依赖注入值
- 不可变数组
property标签+array标签+多个value标签
// 不可变数组
private String[] strs;
- 可变数组
property标签+list标签+多个value标签
// 可变数组
private List<String> list;
4.map依赖注入值
property标签+map标签+多个entry标签
// map
private Map<String,String> map;
5.属性properties依赖注入值
property标签+props标签+多个prop标签
// properties
private Properties properties;
6.自定义引用类型数组
property标签+array标签+多个bean标签
// 自定义类型
private UserService[] userServices;
数组、map、properties、注入值 、自定义引用类型数组打印结果
多配置文件
多配置文件加载方式
使用spring在数据库中查询数据
bean管理和依赖注入的应用
1.dao实现类代码
public class AccountDaoImpl implements AccountDao {
private DruidDataSource druidDataSource;
public void setDruidDataSource(DruidDataSource druidDataSource) {
this.druidDataSource = druidDataSource;
}
@Override
public List<Account> findAll() {
/*
//创建连接池
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/spring_db");
druidDataSource.setUsername("root");
druidDataSource.setPassword("root");
*/
//定义数据库对象
DruidPooledConnection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
List<Account> list = new ArrayList<Account>();
try {
//获取连接
conn = druidDataSource.getConnection();
//编写sql
String sql = "select * from account";
//预编译sql
stmt = conn.prepareStatement(sql);
//参数设置
//执行sql语句
rs = stmt.executeQuery();
//遍历结果集
while (rs.next()) {
Account account = new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
list.add(account);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭连接资源
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return list;
}
}
2.配置文件代码
<?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="ds" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 配置service对象-->
<bean id="as" class="com.qcby.service.impl.AccountServiceImpl">
<property name="accountDao" ref="ad"/>
</bean>
<!-- 配置dao对象-->
<bean id="ad" class="com.qcby.dao.impl.AccountDaoImpl">
<property name="druidDataSource" ref="ds"/>
</bean>
</beans>
整体流程:
将dao注入到service中,dao中操作数据库,service只要调方法,service内部就将dao调用起来,对应的数据就返回到service。
bean标签中,id可以随便起,name要对应class中相应的有set方法的变量,ref对应定义了上述变量的class类的在配置文件中的id值
2024/05/17
IOC注解式开发
重点:开启注解扫描!!!
<context:component-scan base-package="com.qcby"/>
引例:
@Component(value = "us")
//⬆等价于<bean id="us" class="com.qcby.service.impl.UserServiceImpl"/>
//@Component() 等价于 @Component(value = "userServiceImpl")
public class UserServiceImpl implements UserService {
@Override
public void hello() {
System.out.println("业务层:你好");
}
}
测试:
public class UserServiceTest {
@Test
public void run1() {
//加载配置文件,开启其配置的注解扫描
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService us = (UserService) ac.getBean("us");
us.hello();
}
}
bean管理类常用的4个注解(作用相同,推荐使用在不同的分层上)
- @Component 普通的类
- @Controller 表现层的类
- @Service 业务层的类
- @Respository 持久层的类
依赖注入相关注解
与配置相比的优势:不用加set方法或者构造方法
-
@Value:用于注入简单类型(基本类型+字符串)
-
@Autowired:默认按类型进行自动装配(自定义引用类型)(即:bean注解是什么名字不重要,是类就行)
-
@Qualifier:不能单独使用,必须和@Autowired一起使用,不按照类型注入,强制使用名称注入(即:一起使用时,不仅得是相应的类,并且bean注解名称得一致),使用value参数指定名称(自定义引用类型)
-
@Resource:java提供的注解,也可以达到强制使用名称注入的作用,此注解是单独使用的,且用name参数指定名称,不可省略name(@Qualifier使用value指定名称),可以达到@Autowired+@Qualifier的作用
//等价于<bean id="car" class="com.qcby.entity">
@Component
public class Car{
}
//等价于<property name="person" ref="kkk"/>
@Resource(name="kkk")
private Person person;
例:
Car类
//等价于<bean id="car" class="com.qcby.entity"/>
@Component
public class Car {
@Value("奔驰")
private String name;
//推荐使用包装类型,因为double默认值为0,也算一个值,Double默认值为null
@Value("50000.00")
private Double money;
/*@Autowired
//使用@Qualifier
@Qualifier("kkk")*/
//等价于<property name="person" ref="kkk"/>
@Resource(name="kkk")
private Person person;
@Override
public String toString() {
return "Car{" +
"name='" + name + '\'' +
", money=" + money +
", person=" + person +
'}';
}
}
Person类
//不使用@Qualifier或者@Resource
//@Component
//使用@Qualifier或者@Resource
@Component("kkk")
public class Person {
@Value("张三")
private String pname;
@Override
public String toString() {
return "Person{" +
"pname='" + pname + '\'' +
'}';
}
}
测试类
public class UserServiceTest {
@Test
public void run1() {
//加载配置文件,开启其配置的注解扫描
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car = (Car) ac.getBean("car");
System.out.println(car);
}
}
生命周期注解
-
@Scope:取值 singleton(单例) prototype(多例)
随着配置文件的创建而创建,获取对象的时候才创建
如下图,若只是读取配置文件,单例时下述方法会执行,多例时不会执行
初始化方法和销毁方法
-
@PostConstruct:相当于init-method 该注解作用到方法上
-
@PreDestory:相当于destory-method 该注解作用到方法上
单例时:配置文件加载后,无需等所在类创建,就将该方法调用起来
多例时:所在类创建后,就将该初始化方法调用起来
IOC纯注解开发
即:使用配置类代替配置文件
- @Configuration:声明当前类为配置类
- @ComponentScan(“包名”):扫描指定的包路径
- @Import:若有多个配置类,在主配置类中使用该注解导入其他配置类
- @Bean:只能写到方法上,表明使用此方法创建一个对象,并把创建好的对象保存到IOC容器中
@Bean
public DruidDataSource createDataSource() {
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
/*等价于
<bean id="ds" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_db"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
* */
创建工厂加载配置类
new AnnotationConfigApplicationContext(SpringConfig.class)
Ctrl+H查看继承体系
配置文件vs配置类
//加载配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//加载配置类
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
2024/05/18
Spring整合Junit
目的:简化测试开发
步骤:
- 导入依赖 spring-test
@RunWith(SpringJUnit4ClassRunner.class)
声明测试类为spring整合junit的类@ContextConfiguration("classpath:applicationContext.xml")
加载配置文件@Autowired
注入要用于测试的类
导入依赖
<!--spring整合junit-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
<scope>test</scope>
</dependency>
Spring整合Junit纯注解开发
其他步骤与上述一致,只是
@ContextConfiguration("classpath:applicationContext.xml")
加载配置文件
更改为
@ContextConfiguration("classes:SpringConfig.class")
加载配置类
-------End!-------