
目录
9、代理模式
9.2 加深理解
9.3 动态代理都没动态代理
10. AOP
10.1 什么是AOP
10.2 AOP在Spring中的作用
10.3 使用Spring实现AOP
9、代理模式
角色分析:
- 抽象角色:一般会使用接口或者抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理别人的角色,里面处理一些业务
- 客户:访问代理对象的人
步骤:
1.接口
//租房
public interface Rent {
public void rent();
}
2.真实角色
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房东要出租房子");
}
}
3.代理角色
public class Proxy implements Rent{
// 代理角色第一件事,找房东搭伙 先用组合,少用继承(有局限)
private Host host;//组合
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
@Override
public void rent() {
seeHouse();
host.rent();
contract();
fare();
}
//看房
public void seeHouse(){
System.out.println("中介带你看房");
}
//签合同
public void contract(){
System.out.println("签租赁合同");
}
//收中介费
public void fare(){
System.out.println("收中介费");
}
}
4.客户端访问代理
public class Client {
public static void main(String[] args) {
//房东要租房子
Host host = new Host();
//中介
Proxy proxy = new Proxy(host);
proxy.rent();
}
}
代理模式的好处:
- 可以使真实角色的 *** 作更加纯粹,不用去关注一些公共的业务
- 公共业务交给代理角色,实现业务分工
- 公共业务发生扩展时,方便集中管理
缺点:
- 一个真实角色就会产生一个代理角色:代码量会翻倍,开发效率变低
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的,不是我们直接写好的
- 动态代理分为两大类:基于接口的动态代理、基于类的动态代理
- 基于接口----JDK动态代理
- 基于类:cglib
- java字节码实现:javasist 【常用】
需要了解两个类:Proxy:代理,InvocationHandler:调用处理程序
- proxy这个类用来动态生成代理对象
- InvocationHandler用来处理业务
- 模板
public class ProxyInvocationHandler implements InvocationHandler {
//与业务接口组合
private Object Target;
//set方法 注入业务
public void setTarget(Object target) {
Target = target;
}
//生成代理类
//获取当前类的加载器,获取业务的接口,当前对象
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
Target.getClass().getInterfaces(),this);
}
//处理业务,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//niubi
log(method.getName());
Object result = method.invoke(Target, args);
return result;
}
//添加日志
public void log(String msg){
System.out.println("[debug]调用了"+msg+"方法");
}
}
动态代理的好处:
- 可以使真实角色的 *** 作更加纯粹,不用去关注一些公共的业务
- 公共业务交给代理角色,实现业务分工
- 公共业务发生扩展时,方便集中管理
- 一个动态代理类代理的一个接口,一般就是对应的一类业务
- 一个动态代理类可以代理多个类,只要是实现了同一个接口即可
aop(aspect oriented programming):面向切面编程。通过预编译的方式和运行期动态代理实现程序功能的统一维护的一种技术。
10.2 AOP在Spring中的作用提供声明式事务:允许用户自定义切面
- 横切关注点:跨越应用程序多个模块的方法或功能。即:与我们逻辑无关的,但是我们需要专注的部分,就是横切关注点。如:日志,安全,缓存,事务等等
- 切面(aspect):横切关注点被 模块化 的特殊对象。即:它是一个类
- 通知(advice):切面必须要完成的工作。即:它是类中的一个方法
- 目标(target):被通知的对象
- 代理(proxy):向目标对象应用通知之后创建的对象
- 切入点(PointCut):切面通知 执行的 “地点” 的定义
- 连接点(joinPoint):与切入点匹配的执行点
使用AOP织入,需要导入一个依赖包
org.aspectj
aspectjweaver
1.9.4
10.3.1 方式一:使用spring的API接口
public class AfterLog implements AfterReturningAdvice {public class Log implements MethodBeforeAdvice {
动态代理代理的是接口,静态代理代理的是实体类
- 1.配置了 前置日志和后置日志
- 2.准备了UserService和UserServiceImpl实体类 实现了增删改查
配置:
log
public class Log implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println(method.getClass().getName()+"类,执行了"+method.getName()+"方法");
}
}
public class AfterLog implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了"+method.getName()+"方法"+returnValue);
}
}
测试:
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理代理的是UserService接口
UserService userservice = (UserService) context.getBean("userService");
userservice.query();
}
}
10.3.2 方式二:使用自定义类实现AOP
自定义log类
public class DiyPointCut {
public void before(){
System.out.println("========方法执行前=========");
}
public void after(){
System.out.println("========方法执行后=========");
}
}
配置:
测试:
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理代理的是UserService接口
UserService userservice = (UserService) context.getBean("userService");
userservice.query();
}
}
10.3.3 方式三:使用注解实现AOP
自定义一个类充当切面:
//方式三:使用注解方式实现AOP
@Aspect //标注这个类是一个切面
public class AnnotationPointCut {
@Before("execution(* com.hardy.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("========方法执行前=========");
}
@After("execution(* com.hardy.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("========方法执行后=========");
}
//在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
@Around("execution(* com.hardy.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint pj) throws Throwable {
System.out.println("========环绕前=========");
Signature signature = pj.getSignature();//获得签名
System.out.println("signature:"+signature);//打印调用的方法
//执行方法
Object proceed = pj.proceed();
System.out.println("========环绕后=========");
}
}
配置:
测试:
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理代理的是UserService接口
UserService userservice = (UserService) context.getBean("userService");
userservice.query();
}
}
结果:环绕在最外层最早和最晚执行,
========环绕前=========
signature:void com.hardy.service.UserService.query()
========方法执行前=========
查询了一条数据
========方法执行后=========
========环绕后=========
11. 整合Mybatis
步骤:
- 1.导入相关jar包
- Junit
- mybatis
- MySQL
- spring相关
- aop织入
- mybatis-spring 【new】
配置:
junit
junit
4.13.1
test
mysql
mysql-connector-java
5.1.47
org.mybatis
mybatis
3.5.7
org.springframework
spring-webmvc
5.1.19.RELEASE
org.springframework
spring-jdbc
5.1.9.RELEASE
org.aspectj
aspectjweaver
1.9.4
org.mybatis
mybatis-spring
2.0.2
maven 资源导出问题
src/main/java
**/*.properties
**/*.xml
false
src/main/resources
**/*.properties
**/*.xml
false
- 2.编写配置文件
- 3.测试
1.编写实体类
@Data
public class User {
private int id;
private String name;
private String pwd;
}
2.编写核心配置文件
mybatis-config.xml
3.编写接口
UserMapper
public interface UserMapper {
List selectUser();
}
4.编写Mapper.xml
5.测试
@Test
public void test() throws IOException {
String resource = "mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = sessionFactory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List users = mapper.selectUser();
for (User user : users) {
System.out.println(user);
}
}
注意点:
1.找不到类就是maven资源导出问题 target中没有导出文件
2.编写完mapper.xml文件后,一定要去mybatis-config.xml中绑定mapper
3.数据库UTC设置 Asia/Shanghai
4.工具类放下下面
1.编写数据源配置
2.sqlSessionFactory
3.sqlSessionTemplete
- spring-dao.xml
4.给接口添加实现类
//给接口添加实现类
public class UserMapperImpl implements UserMapper{
//原来我们所有 *** 作都使用sqlsession,现在所有都使用SqlSessionTemplate,他俩一样
private SqlSessionTemplate sqlSession;
//spring万物皆注入 一定要来个set方法
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public List selectUser() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
5.将自己写的实现类,注入到spring中
6.测试
@Test
public void test() throws IOException {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper mapper = (UserMapper) context.getBean("userMapper");
for (User user : mapper.selectUser()) {
System.out.println(user);
}
}
方式二 SqlSessionDaoSupport
spring-dao.xml
实现类:UserMapperImpl2
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
@Override
public List selectUser() {
// SqlSession sqlSession = getSqlSession();
// UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// return mapper.selectUser();
return getSqlSession().getMapper(UserMapper.class).selectUser();
}
}
applicationContext.xml
测试:
@Test
public void test() throws IOException {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper mapper = (UserMapper) context.getBean("userMapper2");
for (User user : mapper.selectUser()) {
System.out.println(user);
}
}
12、声明式事务
12.1 回顾事务
- 把一组业务当成一个业务来做,要么都成功,要么都失败
- 事务在项目开发中,十分的重要,涉及到数据的一致性问题,不能马虎
- 确保完整性和一致性
事务的ACID原则:
- 原子性(atomic)
- 要么都成功,要么都失败 - 一致性(consistency)
- *** 作前和 *** 作后,数据总量不变 - 隔离性(isolation)
- 多个业务 *** 作同一资源,不能互相干扰,防止数据损坏 - 持久性(durability)
- 事务一旦提交,不可回滚,无论系统发生什么问题,结果都不受影响,被持久化的写到存储器中。
增删改需要事务,查询不需要(查询设置为只读)
- 声明式事务:AOP 【交由容器管理事务】
- 编程式事务:需要在代码中,进行事务的管理 【需要改变代码】
12.2.1 补充:spring中的七种事务传播属性:propagation 传播
required(依赖):支持当前事务,如果当前没有事务,就新建一个事务 【默认】
supports(支持):支持当前事务,如果当前没有事务,就以非事务的方式执行
mandatory(强制):支持当前事务,如果当前没有事务,就抛出异常
required_new:新建事务,如果当前存在事务,把当前事务挂起
not_supported:以非事务方式执行 *** 作,如果当前存在事务,就把当前事务挂起
never:以非事务方式执行,如果当前存在事务,则抛出异常
nested(嵌套):支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务
例如:
真实开发
12.2.2 案例
x
12.2.3 思考:为什么需要事务?
- 如果不配置事务,可能存在数据提交不一致的情况
- 如果我们不在spring中去配置声明式事务,我们就需要在代码中手动配置事务
- 事务在项目的开发中十分重要,涉及到数据的一致性和完整性问题
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)