- 我的理解是有一个类(目标类)实现了某个接口,再写另一个代理类也实现了这个接口的方法,该方法里有目标类实现的方法,还有许多服务于这个目标类方法的其他代码。到时候直接接口声明调用实现对象,用代理类的方法实现增强。
- 但这会导致如果有许多接口的功能都需要增强时,每个接口都得写一个代理类,这就会导致代码的冗杂,动态代理由此诞生。
- 在JDK动态代理中目标对象仍然需要实现相关接口,但代理对象不需要。
- Proxy.newProxyInstance()这个方法可以实现返回一个代理对象,不过里面需要传的参数有点麻烦,一般用一个工厂类写一个方法实现该方法。
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
//target为目标类,可以用工厂类构造方法传入
public Object getAgent(){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理功能");
Object obj = method.invoke(target,args);
return obj;
}
});
}
CGLib动态代理
- 又叫子类代理,通过在内存中构建子类对象,重写父类的方法实现功能的增强,目标对象可以不实现接口。通过对象字节码框架ASM实现的。
- 被代理的类不能为final,目标对象的方法不能为final和static。
- 工具类Enhancer en =new Enhancer(),en.creater();完成代理对象的创建
1.界面层:接收客户端输入,调用业务逻辑层进行处理,返回结果给客户端
2.业务逻辑层:进行整个项目的业务处理,向上为界面层处理结果,向下向数据访问层要数据。
3.数据访问层:专门用来数据库的增删改查,向上为业务逻辑层提供数据
三层架构优点:
- 结构清晰,耦合性低,分工明确
- 可维护,扩展性高
- 利于标准化
- 开发人员可以只关注整个结构某一层的功能实现
- 利于各层逻辑的复用
常用的框架SSM:
- Spring:是整合其他框架的框架,核心是IOC和AOP。
- SpringMVC:是Spring中的一员,专门用来优化控制器(Servlet)的,提供极简单数据提交,数据携带,页面跳转功能
- MyBatis:是持久化层的一个框架,进行数据库访问的优化,专注SQL语句,极大简化了JDBC。
- 导入依赖
org.mybatis mybatis 3.5.6 mysql mysql-connector-java 5.1.32
- 指定资源文件(之后打包不会丢失)
src/main/resources ***.properties
- 新建properties文件:
jdbc.driverClassName = com.mysql.jdbc.Driver jdbc.url = jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8 jdbc.username = jdbc.password =
- 新建SqlMapConfig.xml文件:
- 具体Map文件
select username,password,phone,create_time from user
- 测试类
public class UserTest {
@Test
public void testGetByPhone() throws IOException {
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory =new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = factory.openSession();
User user = sqlSession.selectOne("hzp.getByPhone",1111111);
System.out.println(user);
sqlSession.close();
}
@Test
public void testGetByName() throws IOException {
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = factory.openSession();
List list = sqlSession.selectList("hzp.getByName","ha");
list.forEach(user -> System.out.println(user));
sqlSession.close();
}
}
- 可以进行实体类别名注册
//单类注册//批量注册,别名为类名的驼峰命名法
- 设置日志输出
- 动态代理7规范
1.xml文件与实现的接口在同一目录下
2.xml文件与接口的文件名一致,后缀不管
3.xml文件中标签的id值与接口中的方法名一致
4.xml文件中标签的parameterType与接口中方法的参数名一致
5.xml文件中标签的resultType与接口方法返回值一致
6.xml文件的nammespace属性必须是接口的完全限定名称
7.在xml配置文件中注册mapper文件时,使用class==接口的完全限定名称 - 动态代理具体步骤
1.建表
2.建maven工程
3.改目录
4.添加依赖
5.建properties文件到resources目录下
6.添加SqlMapConfig.xml文件
7.添加实体类
8.新建mapper文件夹,建Mapper接口
9.在Mapper文件夹下,建Maper.xml文件,完成增删改查功能
目录
- 可以用注释
//接口方法
List getByNameOrBirthday(
@Param("columnName")
String name,
@Param("columnValue")
String value);
//获取对应的字符串,不过更推荐用map实现
select *
from user
where ${columnName} like concat('%',#{columnValue},'%');
其他的一些方法
//username是user类中的username,两者需一样
select
from user
and username like concat('%',#{username},'%')
and id = #{id}
and birthday = #{birthday}
//接口中对应方法 List getByArray(Integer []array);
select
from user
where id in
#{id}
//接口中对应方法List getByMap(Map map),birthdayBegin和birthdayEnd为map中的name
select *
from user
where birthday between #{birthdayBegin} and #{birthdayEnd};
//返回多个map
select id,username,birthday
from user
where username like concat('%',#{name},'%');
//update方法
update user
username = #{username},
password = #{password},
birthday = #{birthday},
where id = #{id}
//将user和orders表关联,customer有list属性,用collection接收
select u.id,username,o.id oid,o.num
from orders o left join user u on o.uid = u.id
where u.id = #{id}
网课地址



