前言:学习自https://www.bilibili.com/video/BV1NE411Q7Nx?p=9
一、面向接口编程
1、简介
-
根本原因:解耦,可扩展,提高复用性。
-
在分层开发中,上层不用管具体的实现,大家都遵守共同的标准,使得开发更加规范化,简便化。
-
使主要精力放到各对象之间的写作关系上,减少在各种功能对象的内部实现上花过多精力。
2、关于接口
- 接口是定义(规范,约束)与实现的分离
- 接口本身反映了系统设计人员对系统的抽象理解
- 接口有两类:一类是对一个个体的抽象,它可对应一个抽象体(abstract class); 另一类是对一个个体某一方面的抽象,即对应一个抽象面(interface)
- 接口设计与非接口设计是针对复用技术而言的,与面向对象或面向过程不是一个问题,而更多的体现则是对系统整体的架构
二、使用注解开发
1、实例测试
1、编写接口
已在接口中使用注解,替代了UserMapper.xml及其配置
public interface UserMapper {
@Select("SELECT * FROM user")
List<User> getUsers();
//方法存在多个参数,则所有参数必须加@Param注解
@Select("SELECT * FROM user WHERE id = #{id} AND name = #{name}")
User getUserByIdANDName(@Param("id") int id, @Param("name") String name);
//(#{id}, #{name}, #{pwd})在传入的User对象中取一一对应的属性值
@Insert("INSERT INTO user(id, name, pwd) VALUES (#{id}, #{name}, #{pwd})")
int addUser(User user);
@Update("UPDATE user SET name = #{name}, pwd = #{pwd} WHERE id = #{id}")
int updateUser(User user);
@Delete("DELETE FROM user WHERE id = #{id}")
int deleteUser(@Param("id") int id);
}
附:当然,同xml方式一样,也要在mybatis核心配置文件中注册mapper,使用xml方式时,属性为resource,使用注解方式时,属性为class
2、编写测试类
public class UserDaoTest {
@Test
public void testGetUsers() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.getUsers();
for (User user : users) {
System.out.println(user);
}
sqlSession.close();
}
......不再赘述
}
2、关于@Param注解
@Param注解用于给方法参数起一个名字。以下是总结的使用原则:
- 在方法只接受一个参数的情况下,可以不使用@Param。
- 在方法接受多个参数的情况下,建议一定要使用@Param注解给参数命名。
- 如果参数是 JavaBean , 则不能使用@Param。
- 不使用@Param注解时,参数只能有一个,并且是Javabean。
3、#与$的区别
- #{} 的作用主要是替换预编译语句(PrepareStatement)中的占位符? 【推荐使用】
INSERT INTO user (name) VALUES (#{name});
INSERT INTO user (name) VALUES (?);
- ${} 的作用是直接进行字符串替换
INSERT INTO user (name) VALUES ('${name}');
INSERT INTO user (name) VALUES ('kuangshen');
4、官方文档的建议
使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。
选择何种方式来配置映射,以及认为是否应该要统一映射语句定义的形式,完全取决于你和你的团队。 换句话说,永远不要拘泥于一种方式,你可以很轻松的在基于注解和 XML 的语句映射方式间自由移植和切换。
5、部分原理的补充
(1)反射机制
对应Mapper机制
三种获取Class的方式:
- 利用对象调用getClass()方法获取该对象的Class实例;
- 使用Class类的静态方法forName(),用类的名字获取一个Class实例 ;
- 运用.class的方式来获取Class实例
(2)动态代理
代理模式的例子:
/*
1.真实角色和代理角色要实现同一个接口
2.代理角色要代理真实角色
好处:代理角色可以做真实角色分外的事,从而真实角色专注做自己分内的事
*/
public class StaticProxy {
public static void main(String[] args) {
You you = new You();
WeddingCompany weddingCompany = new WeddingCompany(you);
/*
这也是多线程Thread的原理
new Thread(一个实现Runnable接口的类).start(),而且Thread本身也实现了Runnable接口
*/
weddingCompany.HappyMarry();
}
}
interface Marry {
void HappyMarry();
}
//真实角色,你去结婚
class You implements Marry {
@Override
public void HappyMarry() {
System.out.println("Marry~");
}
}
//代理角色,帮你结婚
class WeddingCompany implements Marry {
private Marry target;
public WeddingCompany(Marry target) {
//传入真实角色
this.target = target;
}
@Override
public void HappyMarry() {
before();
this.target.HappyMarry(); //真实角色
after();
}
private void before() {
System.out.println("before--arrangement~");
}
private void after() {
System.out.println("after--clear~");
}
}