一、配置maven
在官网中下载mavenMaven – Download Apache Maven
解压下载得压缩包,根据自己的习惯找个目录放进去

按如下图配置maven系统环境变量,目录请按照自己的写,变量名需要和我的一致,然后验证


配置本地仓库,55行左右


Maven-Reps是一个文件夹,放在自己常用的盘里,单独的一个文件夹,不要嵌套。配置镜像(默认的是外网的,速度太慢)mirrors标签中其余内容全部注释掉只剩下这一个就ok,也在setting.xml中
<!-- 阿里云仓库 -->
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
</mirror>
idea2024配置maven如果打开不是这个界面看下一张图



二、创建maven工程




pom.xml里添加的依赖相当于之前项目中lib目录下的jar包,可在以下链接查找依赖坐标Maven Repository: Search/Browse/Explore (mvnrepository.com)
<dependency> <!-- 依赖开始标签 --> <groupId>junit</groupId> <!-- 定义了依赖的组织或公司,这里是JUnit --> <artifactId>junit</artifactId> <!-- 定义了依赖的项目名称,这里是JUnit --> <version>3.8.1</version> <!-- 定义了依赖的版本号,这里是3.8.1 --> <scope>test</scope> <!-- 定义了依赖的范围,这里是测试范围 --> </dependency> <!-- 依赖结束标签 -->
<groupId>:这是依赖的组织或公司的标识符,通常是一个反向域名的形式。这里是junit,表示JUnit这个组织。<artifactId>:这是依赖的项目名称。这里是junit,表示我们依赖的是JUnit项目。<version>:这是依赖的版本号。这里是3.8.1,表示我们依赖的是JUnit的3.8.1版本。<scope>:这是依赖的范围,这里定义为test,表示这个依赖只在测试范围内有效。也就是说,这个JUnit依赖只会在我们执行测试任务时被使用,不会被打包到最终的项目产物中。总结来说,这段文本配置了一个JUnit依赖,版本为3.8.1,并且只在测试范围内有效。这意味着,当我们运行Maven的测试相关命令时(例如
mvn test),Maven会自动下载并使用这个版本的JUnit来进行测试。
三、mybatis入门
1.引入相关依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
依赖爆红是英文本地仓库没有这个东西,点击这个按钮即可下载
这段文本是Maven项目的pom.xml配置文件的一部分,主要用于指定项目的构建设置。以下是对这段文本的详细解释:
<build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> <finalName>untitled1</finalName> </build>- <build>:这是Maven项目的构建配置部分的开始标签。
- <resources>:此标签用于指定项目资源文件的位置和配置。
- <resource>:定义了一个资源文件的配置。
- <directory>src/main/java</directory>:指定资源文件所在的目录,这里是`src/main/java`目录。
- <includes>:指定要包含的资源文件类型。
- <include>**/*.properties</include>:包含所有扩展名为`.properties`的文件。
- <include>**/*.xml</include>:包含所有扩展名为`.xml`的文件。
- <filtering>true</filtering>:表示在处理这些资源文件时启用过滤功能,即可以使用Maven的过滤机制替换文件中的占位符。
- <finalName>untitled1</finalName>:指定构建后的输出文件名,不包含文件扩展名。这里输出的文件名将是untitled1。总结来说,这段配置告诉Maven在构建项目时,要包含src/main/java目录下的所有.properties和.xml文件,并对这些文件进行过滤处理,同时指定构建后的输出文件名应为untitled1。
2.自己创建一个数据库,创建mybatis的核心配置文件
mybatis中文文档网站:MyBatis中文网
自行查看文档解析,复制下方红框框的内容,核心配置文件名为:mybatis-config.xml(不可更改),将value后的值替换成自己的


<!-- 配置环境,默认为development --> <environments default="development"> <environment id="development"> <!-- 事务管理器类型为JDBC --> <transactionManager type="JDBC"/> <!-- 数据源类型为连接池 --> <dataSource type="POOLED"> <!-- 数据库驱动 --> <property name="driver" value="${driver}"/> <!-- 数据库URL --> <property name="url" value="${url}"/> <!-- 数据库用户名 --> <property name="username" value="${username}"/> <!-- 数据库密码 --> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <!-- 映射器列表 --> <mappers> <!-- 引入映射文件 --> <mapper resource="org/mybatis/example/BlogMapper.xml"/> </mappers>- <environments>: 此元素用于配置多个环境,如开发、测试和生产环境。`default`属性指定了默认使用的环境。
- <environment>: 定义了一个具体的运行环境,包括事务管理器和数据源。
- <transactionManager>: 指定事务管理方式,这里使用的是`JDBC`类型的事务管理器。
- <dataSource>: 配置数据源,`type="POOLED"`表示使用连接池。
- <property>: 设置数据源的属性,如数据库驱动、URL、用户名和密码。`${...}`表示这些值将从外部属性文件或配置中获取。
- <mappers>: 用于指定MyBatis的映射文件,这些文件包含了SQL语句和结果映射的定义。
- <mapper>: 引入一个具体的映射文件,这里引入了`BlogMapper.xml`文件。总结来说,这个配置文件设置了MyBatis在开发环境下的数据源和事务管理器,并指定了一个映射文件用于执行SQL语句和映射结果。通过这种方式,MyBatis能够连接到数据库并执行相应的数据操作。
3.创建实体类和mapper接口
在src/main/java目录下
public class User {
private int id;
private String name;
private String pswd;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPswd() {
return pswd;
}
public void setPswd(String pswd) {
this.pswd = pswd;
}
public User() {
}
public User(int id, String name, String pswd) {
this.id = id;
this.name = name;
this.pswd = pswd;
}
}
public interface UserMapper {
Integer addUser(User user);
}
4.创建映射文件
在src/main/resources目录下



5.测试
在src/test/java目录下
public class Test1 {
@Test
public void test1() throws Exception {
String recourse = "mybatis-config.xml";
//读取核心配置文件
Reader reader = Resources.getResourceAsReader(recourse);
//初始化mybatis数据库,创建工厂实例
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(reader);
//创建sqlsession实例
SqlSession session = build.openSession();
//
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User(1008,"33330","5555");
Integer i = mapper.addUser(user);
System.out.println(i);
//提交事务
session.commit();
//释放资源
session.close();
}
}

6.删、改、查代码
public interface UserMapper {
//增
Integer addUser(User user);
//删
Integer deleteUser(Integer id);
//改
Integer updateUser(User user);
//全查
List<User> selectUsers();
//单查
User getUser(Integer id);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mapper.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.UserMapper">
<!--增-->
<insert id="addUser">
insert into user value (#{id},#{name},#{pswd});
</insert>
<!--删-->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{id};
</delete>
<!--改-->
<update id="updateUser" parameterType="pojo.User">
update user set name=#{name},pswd=#{pswd} where id=#{id};
</update>
<!--全查-->
<select id="selectUsers" resultType="pojo.User">
select * from user;
</select>
<!--单查-->
<select id="getUser" resultType="pojo.User" parameterType="java.lang.Integer">
select * from user where id=#{id};
</select>
</mapper>
public class Test1 {
private String recourse = "mybatis-config.xml";
//读取核心配置文件
private Reader reader;
{
try {
reader = Resources.getResourceAsReader(recourse);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//初始化mybatis数据库,创建工厂实例
private SqlSessionFactory build = new SqlSessionFactoryBuilder().build(reader);
//创建sqlsession实例
private SqlSession session = build.openSession();
@Test
public void add() throws Exception {
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User(1011, "33330", "5555");
Integer i = mapper.addUser(user);
System.out.println(i);
//提交事务
session.commit();
//释放资源
session.close();
}
@Test
public void delete() throws Exception {
//创建mapper实例
UserMapper mapper = session.getMapper(UserMapper.class);
Integer i = mapper.deleteUser(1008);
System.out.println(i);
//提交事务
session.commit();
//释放资源
session.close();
}
@Test
public void update() throws Exception {
//创建mapper实例
UserMapper mapper = session.getMapper(UserMapper.class);
Integer i = mapper.updateUser(new User(1005, "upp","tt"));
System.out.println(i);
//提交事务
session.commit();
//释放资源
session.close();
}
@Test
public void selectAll() throws Exception {
//创建mapper实例
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> i = mapper.selectUsers();
System.out.println(i);
//提交事务
session.commit();
//释放资源
session.close();
}
}
四、优化
加入日志功能,首先在pom.xml文件中添加以下依赖,然后在resources文件下创建logback.xml文件
<!-- 添加slf4j日志api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.20</version>
</dependency>
<!-- 添加logback-classic依赖 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- 添加logback-core依赖 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%5level [%thread] - %msg%n</pattern>
</encoder>
</appender>
<logger name="这个地方写包名,如果只有一级包名就空着">
<level value="trace"/>
</logger>
<root level="error">
<appender-ref ref="stdout"/>
</root>
</configuration>
使用lombok简化实体类,在pom.xml中添加相关依赖,之后实体类采用注解的方式
<!-- lombok依赖包 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
/*
* 实体类
* */
@Data//getter、setter方法
@AllArgsConstructor//全参构造
@NoArgsConstructor//无参构造
@ToString
public class User {
private int id;
private String name;
private String pswd;
public User(String name, String pswd) {
this.name = name;
this.pswd = pswd;
}
}
五、mybatis标签
1.多条件查询
两种方法

List<User> getUsers(User user);
<!--多条件查询-->
<!--prefix:设置前缀
suffix:设置后缀
suffixOverrides:要去掉的后缀,只去掉最后一个多余的and
prefixOverrides:要去掉的前缀,只去掉第一个-->
<select id="getUsers" resultType="pojo.User">
select *
from user
<trim prefix="where" suffix=";" prefixOverrides="or" suffixOverrides="and">
<if test="id!=null and id!=''">
id=#{id} and
</if>
<if test="name!=null and name!=''">
or name=#{name} and
</if>
<if test="pswd!=null and pswd!=''">
pswd=#{pswd} and
</if>
</trim>
<!--<where>
<if test="id!=null and id!=''">
id=#{id}
</if>
<if test="name!=null and name!=''">
and name=#{name}
</if>
<if test="pswd!=null and pswd!=''">
and pswd=#{pswd}
</if>
</where>;-->
</select>
@Test
public void selectAll() throws Exception {
//创建mapper实例
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> i = mapper.getUsers(new User("zs",null));
System.out.println(i);
//提交事务
session.commit();
//释放资源
session.close();
}
2.自定义修改
两种方法

Integer updateUser(User user);
<!--条件修改-->
<update id="updateUser" parameterType="pojo.User">
update user
<trim prefix="set" suffix="where id=#{id}" suffixOverrides=",">
<if test="name!=null and name!=''">
name=#{name},
</if>
<if test="pswd!=null and pswd!=''">
pswd=#{pswd},
</if>
</trim>
<!--<set>
<if test="name!=null and name!=''">
name=#{name},
</if>
<if test="pswd!=null and pswd!=''">
pswd=#{pswd},
</if>
</set>
where id=#{id}-->
</update>
@Test
public void update() throws Exception {
//创建mapper实例
UserMapper mapper = session.getMapper(UserMapper.class);
Integer i = mapper.updateUser(new User(5, "update2",null));
System.out.println(i);
//提交事务
session.commit();
//释放资源
session.close();
}
3.自定义新增

Integer addUser(User user);
<!--自定义新增-->
<insert id="addUser" parameterType="pojo.User">
insert into user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id!=null and id!=''">id,</if>
<if test="name!=null and name!=''">name,</if>
<if test="pswd!=null and pswd!=''">pswd</if>
</trim>
<trim prefix="values(" suffix=")" suffixOverrides=",">
<if test="id!=null and id!=''">#{id},</if>
<if test="name!=null and name!=''">#{name},</if>
<if test="pswd!=null and pswd!=''">#{pswd}</if>
</trim>
</insert>
@Test
public void add() throws Exception {
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User("33330", null);
Integer i = mapper.addUser(user);
System.out.println(i);
//提交事务
session.commit();
//释放资源
session.close();
}

4.单条件查询
同switch--case,满足条件就跳出判断

User getUserByid(@Param("id") Integer id, @Param("name") String name, @Param("pswd") String pswd);
<select id="getUserByid" resultType="pojo.User">
select *
from user
# where
<where>
<choose>
<when test="id!=null and id!=''">id=#{id}</when>
<when test="name!=null and name!=''">name=#{name}</when>
<when test="pswd!=null and pswd!=''">pswd=#{pswd}</when>
<otherwise>1=1</otherwise>
</choose>
</where>
</select>
@Test
public void selectOne() throws Exception {
//创建mapper实例
UserMapper mapper = session.getMapper(UserMapper.class);
User zs = mapper.getUserByid(5, "zs", null);
System.out.println(zs);
//提交事务
session.commit();
//释放资源
session.close();
}
5.动态sql(批量操作)
5.1 查

List<User> selectBatch(@Param("ids") Integer[] ids);
<!--
collection:要遍历的集合
open:前缀
close:后缀
separator:分隔符
item:每一个拿到的元素别名
-->
<!--in-->
<select id="selectBatch" resultType="pojo.User" parameterType="java.lang.Integer">
select *
from user
where id in
<foreach collection="ids" open="(" item="id" separator="," close=")">
#{id}
</foreach>
<!--(<foreach collection="ids" item="id" separator=",">
#{id}
</foreach>)-->
</select>
<!--or-->
<!--<select id="selectBatch" resultType="pojo.User" parameterType="java.lang.Integer">
select *
from user
where
<foreach collection="ids" item="id" separator="or">
id=#{id}
</foreach>
</select>-->
@Test
public void selectBatch() throws Exception {
//创建mapper实例
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.selectBatch(new Integer[]{1, 2, 3});
System.out.println(users);
//提交事务
session.commit();
//释放资源
session.close();
}
5.2 删


int delBatch(@Param("ids") Integer[] ids);
<!--通过id批量删除-->
<delete id="delBatch" parameterType="java.lang.Integer">
delete
from user
where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
@Test
public void delBatch() throws Exception {
//创建mapper实例
UserMapper mapper = session.getMapper(UserMapper.class);
int res = mapper.delBatch(new Integer[]{7,8,9,10,11});
System.out.println(res);
//提交事务
session.commit();
//释放资源
session.close();
}

5.3 改
<!--连接数据库的URL-->
<property name="url" value="jdbc:mysql://127.0.0.1:3306/student?allowMultiQueries=true"/>

int upBatch(@Param("users") List<User> users);
<update id="upBatch">
<foreach collection="users" item="user">
update user
<trim prefix="set" suffix="where id=#{user.id};" suffixOverrides=",">
<if test="user.name!=null and user.name!=''">
name=#{user.name},
</if>
<if test="user.pswd!=null and user.pswd!=''">
pswd=#{user.pswd},
</if>
</trim>
</foreach>
</update>
@Test
public void upBatch() throws Exception {
//创建mapper实例
UserMapper mapper = session.getMapper(UserMapper.class);
User update1 = new User(1, "update1", null);
User update2 = new User(2, "update2", null);
List<User> list = Arrays.asList(update1, update2);
int res = mapper.upBatch(list);
System.out.println(res);
//提交事务
session.commit();
//释放资源
session.close();
}
5.4 增

int inBatch(@Param("users") List<User> users);
<insert id="inBatch">
<foreach collection="users" item="user">
insert into user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="user.id!=null and user.id!=''">id,</if>
<if test="user.name!=null and user.name!=''">name,</if>
<if test="user.pswd!=null and user.pswd!=''">pswd</if>
</trim>
<trim prefix="values(" suffix=");" suffixOverrides=",">
<if test="user.id!=null and user.id!=''">#{user.id},</if>
<if test="user.name!=null and user.name!=''">#{user.name},</if>
<if test="user.pswd!=null and user.pswd!=''">#{user.pswd}</if>
</trim>
</foreach>
</insert>
@Test
public void inBatch() throws Exception {
//创建mapper实例
UserMapper mapper = session.getMapper(UserMapper.class);
User in1 = new User( "in1", "in1");
User in2 = new User( "in2", "in2");
List<User> list = Arrays.asList(in1, in2);
int res = mapper.inBatch(list);
System.out.println(res);
//提交事务
session.commit();
//释放资源
session.close();
}
5.5 xml文件中sql语句重复部分提炼
<sql id="sel">select * from user</sql>
//将select * from user换成下面这句
<include refid="sel"/>
六、特殊sql
1.模糊查询

List<User> getUsersByNameLike(@Param("name") String name);
<!--模糊查询-->
<!--以下三种可互相替换
"%"#{name}"%";
'%${name}%';
concat('%',#{name},'%');
-->
<select id="getUsersByNameLike" resultType="pojo.User" parameterType="java.lang.String">
<include refid="sel"/>
where name like
"%"#{name}"%";
</select>
@Test
public void getUserByNameLike() throws Exception {
//创建mapper实例
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> list = mapper.getUsersByNameLike("u");
System.out.println(list);
//提交事务
session.commit();
//释放资源
session.close();
}
2.批量删除
传入string类型的参数

int delMore(@Param("ids") String ids);
<delete id="delMore" parameterType="java.lang.String">
delete
from user
where id in(${ids});
</delete>
@Test
public void delMore() throws Exception {
//创建mapper实例
UserMapper mapper = session.getMapper(UserMapper.class);
System.out.println(mapper.delMore("12,13"));
//提交事务
session.commit();
//释放资源
session.close();
}
3.获取新增数据的自增主键
useGeneratedKeys="true"--->当前sql语句使用了自增主键
keyProperty="id"--->自动递增的主键赋值给映射文件的实体类中的id属性


七、自定义字段映射
在数据库的表中字段为user_name,映射到java文件中的userName,这里只说最简单好用的方法
在MyBatis的全局配置中设置开启数据库下划线自动映射为实体类驼峰(如:emp_name映射为empName)
在多条件查询中的代码上修改,后续也有练习

<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

/*
* 实体类
* */
@Data//getter、setter方法
@AllArgsConstructor//全参构造
@NoArgsConstructor//无参构造
@ToString
public class User {
private int id;
private String userName;
private String pswd;
public User(String name, String pswd) {
this.userName = name;
this.pswd = pswd;
}
}

八、mybatis缓存
缓存:本次查询到的数据暂存,下次同一个查询条件下不访问数据库直接从缓存拿,前提是数据表没有被改变
一级缓存:同一个sqlSession查询的
二级缓存:同一个sqlSessionFactory查询的
九、多表查询
emp:员工表
emp_id emp_name emp_sex dept_id
dept:部门表
dept_id dept_name
仅做查询练习

1.实体类设计
/*
* 部门表
* */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Dept {
private int deptId;
private String deptName;
private List<Emp> emps;
}
/*
* 部门表
* */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Emp {
private int empId;
private String empName;
private String empSex;
private Dept dept;
}
2.查询员工信息包括部门
核心配置文件
<setting name="autoMappingBehavior" value="FULL"/>--->resoultMap是否嵌套都自动映射



Emp getEmpById(@Param("id") int id);
<resultMap id="emprs" type="pojo.Emp">
<association property="dept" javaType="pojo.Dept"></association>
</resultMap>
<select id="getEmpById" resultMap="emprs" parameterType="int">
select *
from emp
left join dept on emp.dept_id = dept.dept_id
where emp_id = #{id};
</select>
@Test
public void selEmp() throws Exception {
//创建mapper实例
EmpMapper mapper = session.getMapper(EmpMapper.class);
System.out.println(mapper.getEmpById(1));
//提交事务
session.commit();
//释放资源
session.close();
}
3.查询部门下的所有员工

//empmapper
List<Emp> getAllEmpByDeptId(@Param("id") int id);
//deptmapper
Dept getDeptById(@Param("id") int id);
<resultMap id="deptrs" type="pojo.Dept">
<collection property="emps" column="dept_id" select="mapper.EmpMapper.getAllEmpByDeptId"></collection>
</resultMap>
<select id="getDeptById" resultMap="deptrs" parameterType="int">
select *
from dept where dept.dept_id=#{id};
</select>
@Test
public void selDept() throws Exception {
//创建mapper实例
DeptMapper mapper = session.getMapper(DeptMapper.class);
System.out.println(mapper.getDeptById(2));
//提交事务
session.commit();
//释放资源
session.close();
}
十、mybatis注解开发
一般的增删改查,xml文件中不写对于的雨具,但是需要有xml


一对多

十一、mybatis分页插件
1、pom.xml中导入依赖
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
2、在MyBatis核心配置文件中配置分页插件(mybatis-config.xml)
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="helperDialect" value="mysql"/>
</plugin>
</plugins>
pageNum:当前页的页码
pageSize:每页显示的条数
navigatePages:设置导航分页的页码数

@Test
public void selectAll() throws Exception {
//创建mapper实例
UserMapper mapper = session.getMapper(UserMapper.class);
//在查询操作开始之前开启分页
PageHelper.startPage(2, 3);
//执行sql
List<User> i = mapper.getUsers(new User());
//在查询获取list集合之后,获取分页相关的数据
PageInfo<User> pageInfo = new PageInfo<>(i,2);
System.out.println(pageInfo);
//提交事务
session.commit();
//释放资源
session.close();
}
十二、Spring基础入门案例
1.新建Maven工程,导入spring依赖
<!-- 基于Maven依赖传递性,导入spring-context依赖即可导入当前所需所有jar包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
2.编写User.java
public class User {
public User(){
System.out.println("User类中的无参构造方法被调用...");
}
public void add(){
System.out.println("add....");
}
}
3.编写spring核心配置文件(applicationContext.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--
id:唯一标识
class:要创建的对象的全类名(包名+类名)
-->
<bean id="user" class="com.hait.userTest.User"></bean>
</beans>
4.编写测试类
@Test
public void testUserOb(){
//加载spring核心配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取创建对象,使用了User类的无参构造,使用反射创建
/*
* 反射:
* 1.加载核心配置文件
* 2.对核心配置文件进行解析
* 3.获取bean标签属性值----id和class属性
* 4.使用反射根据类的全路径创建对象
* */
User user = (User) ac.getBean("user");
System.out.println("对象地址"+user);
//使用对象调用方法进行测试
user.add();
}
//反射创建对象
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("com.hait.userTest.User");
User user = (User) clazz.newInstance();//高版本过时
// clazz.getDeclaredConstructor().newInstance();---高版本使用这个
System.out.println("通过反射创建对象:"+user);
}

5.加上日志框架
<!--日志-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.19.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>2.19.0</version>
</dependency>
在resources新建log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数(最小是5秒钟)-->
<configuration monitorInterval="5" status="warn">
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--变量配置-->
<Properties>
<!-- 格式化输出:%date表示日期(可缩写成%d,后同),%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
<!-- %logger{36} 表示 Logger 名字最长36个字符 -->
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss,SSS} %highlight{%-5level} [%t] %highlight{%c{1.}.%M(%L)}: %msg%n" />
<!-- 定义日志存储的路径 -->
<property name="FILE_PATH" value="log" />
<!--<property name="FILE_NAME" value="myProject" />-->
</Properties>
<!--此节点有三种常见的子节点:Console,RollingFile,File-->
<appenders>
<!--console节点用来定义输出到控制台的Appender-->
<!--target:SYSTEM_OUT或SYSTEM_ERR,一般只设置默认:SYSTEM_OUT-->
<console name="Console" target="SYSTEM_OUT">
<!--输出日志的格式,默认为:%m%n,即只输出日志和换行-->
<PatternLayout pattern="${LOG_PATTERN}"/>
<!--阈值过滤器,控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
</console>
<!-- <!–文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用–>-->
<!-- <File name="Filelog" fileName="${FILE_PATH}/test.log" append="false">-->
<!-- <PatternLayout pattern="${LOG_PATTERN}"/>-->
<!-- </File>-->
<!-- 这个会打印出所有的debug及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileDebug" fileName="${FILE_PATH}/debug.log" filePattern="${FILE_PATH}/debug/DEBUG-%d{yyyy-MM-dd}_%i.log.gz">
<!--阈值过滤器,控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
<!--如果配置的是“%d{yyyy-MM}”,滚动时间单位就是月。“%d{yyyy-MM-dd}”,滚动时间单位就是天-->
<PatternLayout pattern="${LOG_PATTERN}"/>
<!--指定滚动日志的策略,就是指定新建日志文件的时机-->
<Policies>
<!--interval属性用来指定多久滚动一次,时间单位取决于<PatternLayout pattern>,modulate属性调整时间,true:0点为基准滚动,false:服务器启动时间开始滚动-->
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15">
<!--删除15天之前的日志-->
<Delete basePath="${FILE_PATH}" maxDepth="2">
<IfFileName glob="*/*.log.gz" />
<IfLastModified age="360H" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
<!-- 这个会打印出所有的warn及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/info/INFO-%d{yyyy-MM-dd}_%i.log.gz">
<!--阈值过滤器,控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<!--interval属性用来指定多久滚动一次,时间单位取决于<PatternLayout pattern>,modulate属性调整时间,true:0点为基准滚动,false:服务器启动时间开始滚动-->
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log" filePattern="${FILE_PATH}/error/ERROR-%d{yyyy-MM-dd}_%i.log.gz">
<!--阈值过滤器,控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<!--interval属性用来指定多久滚动一次,时间单位取决于<PatternLayout pattern>,modulate属性调整时间,true:0点为基准滚动,false:服务器启动时间开始滚动-->
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<!--启用异步日志,阻塞队列最大容量为20000,超出队列容量时是否等待日志输出,不等待将直接将日志丢弃-->
<Async name="Async" bufferSize="20000" blocking="true">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFileDebug"/>
<AppenderRef ref="RollingFileInfo"/>
<AppenderRef ref="RollingFileError"/>
</Async>
</appenders>
<!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
<!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
<logger name="org.mybatis" level="info" additivity="false">
<AppenderRef ref="Async"/>
</logger>
<!--监控系统信息-->
<!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。-->
<Logger name="org.springframework" level="info" additivity="false">
<AppenderRef ref="Async"/>
</Logger>
<!--root 节点用来指定项目的根日志,level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.-->
<root level="debug">
<AppenderRef ref="Async" />
</root>
</loggers>
</configuration>
十三、IoC控制反转
Spring通过IoC容器管理所有java对象的实例化和初始化,控制对象与对象之间的依赖关系。
我们将IoC管理的Java对象成为Spring Bean,它与使用关键字new创建的Java对象没有任何区别。
是一种思想,不是一种技术。
依赖注入:1.setter注入2.构造器注入
十四、基于xml管理bean
在user类中添加两个属性
public class User {
private String name;
private Integer age;
public User(){
System.out.println("User类中的无参构造方法被调用...");
}
public void add(){
System.out.println("add....");
}
}
1.获取bean的方式
1.1 根据id获取

1.2 根据类型获取
两个bean的id不同但是class的值是同一个的话会报NoUniqueBeanDefinitionException错

1.3 根据id+类型获取


1.4 class的值能否是接口
该接口有只有一个实现类的话,可以。

2.setter注入
public class Student {
private int age;
private String name;
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student() {
}
public Student(int age, String name) {
this.age = age;
this.name = name;
System.out.println("student有参构造被执行....");
}
}
新建setterIn.xml文件,仅仅是为了区分,标准的核心配置文件名是applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.setter注入-调用的是实体类中的setter方法
name:属性名
value:属性值
ref:属性值为对象而非普通文本
-->
<bean id="student" class="com.hait.pojo.Student">
<property name="name" value="张三"/>
<property name="age" value="18"/>
</bean>
</beans>

3.构造器注入
<!--2.构造器注入-->
<bean id="student" class="com.hait.pojo.Student">
<constructor-arg name="name" value="zhangsan"/>
<constructor-arg name="age" value="22"/>
</bean>

4.特殊值的处理
4.1 字面量赋值
<property name="name" value="张三"/>
4.2 null值
int类型不可以赋空值
<property name="age">
<null></null>
</property>
![]()
4.3 xml实体
<property name="name" value="<>"/>

4.4 CDATA节
<![CDATA[内容]]>
<property name="name">
<value><![CDATA[a<b]]></value>
</property>
![]()
5.特殊类型属性的注入
按下图设计实体类

测试类中仅使用以下代码
@Test
public void getTest(){
ApplicationContext ac = new ClassPathXmlApplicationContext("exam1.xml");
Teacher tea = (Teacher) ac.getBean("bean的id");
System.out.println(tea);
}
5.1 对象类型属性注入
5.1.1 外部bean注入
<bean id="cla" class="com.hait.pojo.MyClass"/>
<bean id="tea" class="com.hait.pojo.Teacher">
<property name="myClass" ref="cla"/>
</bean>
![]()
5.1.2 内部bean注入
<!--外部bean注入-->
<bean id="tea" class="com.hait.pojo.Teacher">
<property name="myClass">
<bean id="cls" class="com.hait.pojo.MyClass"/>
</property>
</bean>

5.1.3 级联属性赋值
<!--级联属性赋值-->
<bean id="cls1" class="com.hait.pojo.MyClass">
<property name="name" value="1班"/>
</bean>
<bean id="tea" class="com.hait.pojo.Teacher">
<property name="myClass" ref="cls1"/>
<property name="myClass.name" value="2班"/>
</bean>

5.2 数组类型注入
<!--数组类型注入-->
<bean id="tea4" class="com.hait.pojo.Teacher">
<property name="myClass" ref="cls1"/>
<property name="vacation">
<array>
<value>周三</value>
<value>周五</value>
<value>周日</value>
</array>
</property>
</bean>
![]()
5.3 集合类型注入
5.3.1 list集合
准备工作:
<bean id="stu1" class="com.hait.pojo.Student">
<property name="name" value="张三"/>
<property name="age" value="22"/>
</bean>
<bean id="stu2" class="com.hait.pojo.Student">
<property name="name" value="李四"/>
<property name="age" value="12"/>
</bean>
<bean id="stu3" class="com.hait.pojo.Student">
<property name="name" value="王五"/>
<property name="age" value="32"/>
</bean>
方法1:
<!--list集合注入-->
<util:list id="stuList">
<ref bean="stu1"/>
<ref bean="stu2"/>
<ref bean="stu3"/>
</util:list>
<bean id="tea5" class="com.hait.pojo.Teacher">
<property name="myClass" ref="cls1"/>
<property name="students" ref="stuList"/>
<property name="vacation">
<array>
<value>周三</value>
<value>周五</value>
<value>周日</value>
</array>
</property>
</bean>
方法2:
<bean id="tea6" class="com.hait.pojo.Teacher">
<property name="myClass" ref="cls1"/>
<property name="students">
<list>
<ref bean="stu1"/>
<ref bean="stu2"/>
<ref bean="stu3"/>
</list>
</property>
<property name="vacation">
<array>
<value>周三</value>
<value>周五</value>
<value>周日</value>
</array>
</property>
</bean>

5.3.2 map集合
方法1:
<util:list id="stuList">
<ref bean="stu1"/>
<ref bean="stu2"/>
<ref bean="stu3"/>
</util:list>
<util:map id="scores">
<entry key="数学" value="90"/>
<entry key="英语" value="80"/>
<entry key="语文" value="70"/>
</util:map>
<bean id="tea5" class="com.hait.pojo.Teacher">
<property name="myClass" ref="cls1"/>
<!--list集合-->
<property name="students" ref="stuList"/>
<!--map集合-->
<property name="score" ref="scores"/>
<!--数组-->
<property name="vacation">
<array>
<value>周三</value>
<value>周五</value>
<value>周日</value>
</array>
</property>
</bean>
方法2:
<bean id="tea6" class="com.hait.pojo.Teacher">
<property name="myClass" ref="cls1"/>
<!--list集合-->
<property name="students">
<list>
<ref bean="stu1"/>
<ref bean="stu2"/>
<ref bean="stu3"/>
</list>
</property>
<!--map集合-->
<property name="score">
<map>
<entry key="数学" value="90"/>
<entry key="英语" value="80"/>
<entry key="语文" value="70"/>
</map>
</property>
<!--数组-->
<property name="vacation">
<array>
<value>周三</value>
<value>周五</value>
<value>周日</value>
</array>
</property>
</bean>

如果List集合中要传入的类型为String这样的类型
<util:list id="pos">
<value>东</value>
<value>西</value>
<value>南</value>
<value>北</value>
</util:list>
.....
<property name="position" ref="pos"/>
如果map集合传入的是Student类型等

<util:map id="stus">
<entry key-ref="stu1" value-ref="cls1"/>
<entry key-ref="stu2" value-ref="cla"/>
</util:map>
<bean id="tea7" class="com.hait.pojo.Teacher">
<property name="stus" ref="stus"/>
</bean>

5.4 引入外部文件注入
依赖
<!--数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<!--数据源-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.10.1</version>
</dependency>
数据库文件

db.user=root
db.password=root
db.url=jdbc:mysql://localhost:3306/student?serverTimezone=UTC
db.driver=com.mysql.cj.jdbc.Driver
spring核心配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${db.user}"/>
<property name="password" value="${db.password}"/>
<property name="jdbcUrl" value="${db.url}"/>
<property name="driverClass" value="${db.driver}"/>
</bean>
</beans>
测试
@Test
public void getJdbc() throws SQLException, PropertyVetoException {
ApplicationContext ac = new ClassPathXmlApplicationContext("配置文件名");
DataSource source = ac.getBean(ComboPooledDataSource.class);
Connection connection = source.getConnection();
System.out.println(connection);
}

6.基于xml的自动装配
环境准备:三层架构, Controller调用service,service调用dao


首先在userServiceImpl中创建userDao类型的属性并创建setter方法,在addService方法中调用userDao中的addDao方法
其次在controller中创建service类型的属性并创建setter方法,在controlller中调用service中的方法
最后创建测试类进行测试


//userDao
public interface UserDao {
void addDao();
}
//userDaoImpl
public class UserDaoImpl implements UserDao {
@Override
public void addDao() {
System.out.println("userDao中的方法执行了...");
}
}
//userService
public interface UserService {
void addService();
}
//userServiceImpl
public class UserServiceImpl implements UserService {
//1.创建userDao类型的属性,并生成set方法
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void addService() {
System.out.println("addService中的方法执行了...");
/*原生写法*/
/*UserDao userDao = new UserDaoImpl();
userDao.addDao();*/
/*注入后调用dao中的方法*/
userDao.addDao();
}
}
//UserController
public class UserController {
//2.定义service类型的属性并生成set方法
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
public void addUser(){
System.out.println("controller中的方法执行了...");
/*原生写法*/
/*UserService userService = new UserServiceImpl();
userService.addService();*/
/*经过注入,调用service的方法*/
userService.addService();
}
}
//Test
@Test
public void autoBean(){
ApplicationContext ac = new ClassPathXmlApplicationContext(
"bean-auto.xml");
UserController userController = ac.getBean(
"userController", UserController.class);
userController.addUser();
}
//bean-auto.xml
<?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">
<!--1.创建三个对象
2.bean标签中的autowire属性:autowire="byType"根据类型注入,byName:根据名称注入
-->
<bean id="userController" class="com.hait.controller.UserController" autowire="byType"/>
<bean id="userService" class="com.hait.service.impl.UserServiceImpl" autowire="byType"/>
<bean id="userDao" class="com.hait.dao.impl.UserDaoImpl"/>
</beans>
十五、基于注解的方式进行bean管理
注解是代码中的一种特殊标记,格式:@注解名称(属性1=属性值,...)
可以简化xml配置
实际开发中一般用的都是注解
步骤:
1.引入依赖(前面都引入过了)
2.开启组件扫描
spring默认不使用注解装配bean,因此我们需要再spring的xml配置中,通过context:component-scan元素开启自动扫描功能。开启功能后,spring会自动扫描指定的包及其子包下单所有类,如果类上使用了@Component注解,就将该类装配到容器中。
3.使用注解定义bean,下述四个注解功能都是一样的
@Component:描述spring中的bean,可以使用在任何层次
@Repository:一般用于数据访问层(Dao)
@Service:一般用于业务层(Service)
@Controller:一般用于控制层(Controller)
4.依赖注入
@AutoWired:默认是byType
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--开启组件扫描,要扫描的包名写的越具体越好,因为越具体扫描花费的时间越少-->
<!--1.最基本的写法-->
<context:component-scan base-package="com.hait"/>
<!--2.指定要排除扫描的组件
use-default-filters="true“(默认),所设置的包下所有的类都需要扫描,此时可以使用排除扫描
use-default-filters="false“,所设置的包下所有的类都不扫描,此时可以使用包含扫描
-->
<context:component-scan base-package="com.hait">
<!--整合springmvc时,controller由mvc扫描,不需要spring扫描-->
<!--1.根据注解排除-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!--2.根据类型排除(全类名)-->
<!--<context:exclude-filter type="assignable" expression="com.hait.controller.UserController"/>-->
</context:component-scan>
<!--3.仅扫描制定组件-->
<context:component-scan base-package="com.hait" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!--<context:include-filter type="assignable" expression="com.hait.controller.UserController"/>-->
</context:component-scan>
</beans>

1.Autowired
1.1 属性注入

1.2 setter注入
private UserService userService;
//第二种方式:setter注入,其余部分同理
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
1.3 构造方法注入
private UserService userService;
//第三种方式:构造方法注入,其余部分同理
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
1.4 形参上注入
private UserService userService;
public UserController(@Autowired UserService userService) {
this.userService = userService;
}
如果属性有且仅有一个有参构造函数,那么可以省略注解
private UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
1.5 @Autowired+@Qualifier类型+名称注解
若dao层有两个实现类,那么仅仅使用Autowired注解就会报错

解决办法

2.@Resource
高于jdk11或低于jdk8的都需要引入依赖
默认根据名称注入(byName),未指定name时,使用属性名作为name。通过name找不到的话会自动启动byType注入。
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
2.1 根据名称

2.2 不指定名称则根据属性名进行注入

十六、spring全注解开发
使用一个配置类取代配置文件
package com.hait.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration //配置类
@ComponentScan("com.hait") //开启注解扫描
public class SpringConfig {
}
在测试类中测试
@Test
public void autoBean(){
// ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//加载配置类
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
UserController userController = ac.getBean(UserController.class);
userController.addController();
}

spring剩下的:

821

被折叠的 条评论
为什么被折叠?



