栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java(Spring02)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java(Spring02)

Java(Spring02)

参考视频:17. 静态代理模式(狂神)

10. 代理模式
  • 为什么要学习代理模式?因为这就是SpringAOP的底层!【SpringAOP 和 SpringMVC】
  • 代理模式的分类:
    • 静态代理
    • 动态代理

10.1 静态代理
  • 角色分析:
    • 抽象角色:一般会使用接口或者抽象类来解决
    • 真实角色:被代理的角色
    • 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
    • 客户:访问代理对象的人

 
代码步骤:

  1. 接口
package com.zach.demo01;

//租房
public interface Rent {
    
    public void rent();
    
}
  1. 真实角色
package com.zach.demo01;

//房东
public class Host implements Rent{
    
    @Override
    public void rent() {
        System.out.println("房东的猫");
    }
}
  1. 代理角色
package com.zach.demo01;

public class Proxy implements Rent{
    
    private Host host;
    
    public Proxy() {
    }
    
    public Proxy(Host host) {
        this.host = host;
    }
    
    
    @Override
    public void rent() {
        seeHouse();
        host.rent();
        signContract();
        payFee();
    }
    
    //看房子
    public void seeHouse(){
        System.out.println("使用中介的看房子功能");
    }
    
    //签合同
    public void signContract(){
        System.out.println("和中介签租赁合同");
    }
    
    //收中介费
    public void payFee(){
        System.out.println("向中介付钱");
    }
}
  1. 客户端访问代理角色
package com.zach.demo01;

public class Client {
    public static void main(String[] args) {
        //房东要出租房子
        Host host = new Host();
        //代理,中介帮房东租房子。但是,代理角色一般会有其他附属操作。
        Proxy proxy = new Proxy(host);
        
        //你不能面对房东/你无需面对房东,直接找中介去租房即可。
        proxy.rent();
    }
}

 

  • 静态代理模式的优点:
    • 可以使真实角色的操作更加纯粹,无需关注公共的业务。
    • 公共业务交给代理角色,实现了业务的分工。
    • 公共业务发生扩展的时候,方便集中管理。
  • 静态代理模式的缺点:
    • 一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率会变低。
10.2 静态代理(加深理解)
  • 代码:
  • UserService
package com.zach.demo02;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void query();
}
  • UserServiceImpl
package com.zach.demo02;

//真实对象
public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加一个用户");
    }
    
    @Override
    public void delete() {
        System.out.println("删除一个用户");
    }
    
    @Override
    public void update() {
        System.out.println("修改一个用户");
    }
    
    @Override
    public void query() {
        System.out.println("查询一个用户");
    }
    //1.改动原有的业务代码,在大公司中是大忌。
}
  • UserServiceProxy
package com.zach.demo02;

public class UserServiceProxy implements UserService{
    
    private UserServiceImpl userService;
    
    public void setUserService(UserServiceImpl userService) {
        this.userService = userService;
    }
    
    @Override
    public void add() {
        log("add");
        userService.add();
    }
    
    @Override
    public void delete() {
        log("delete");
        userService.delete();
    }
    
    @Override
    public void update() {
        log("update");
        userService.update();
    }
    
    @Override
    public void query() {
        log("query");
        userService.query();
    }
    
    //日志方法
    public void log(String msg){
        System.out.println("[Debug] 使用了"+msg+"方法");
    }
}
  • Client
package com.zach.demo02;

public class Client {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        userService.add();
        UserServiceProxy proxy = new UserServiceProxy();
        proxy.setUserService(userService);
        proxy.add();
    }
}
  • 聊聊AOP
10.3 动态代理
  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的
  • 动态代理分为两大类:基于接口的动态代理、基于类的动态代理
    • 基于接口的 → JDK动态代理【目前使用这个先】
    • 基于类的 → cglib
    • java字节码实现:javasist

 

  • 需要了解两个类:Proxy(代理)、InvacationHandler(调用处理程序)
  • 动态代理的优点:
    • 静态代理有的优点动态代理也有:
      • 可以使真实角色的操作更加纯粹,无需关注公共的业务。
      • 公共业务交给代理角色,实现了业务的分工。
      • 公共业务发生扩展的时候,方便集中管理。
    • 静态代理模式的缺点动态代理没有:
      • 一个动态代理类代理的是一个接口,一般就是对应的一类业务
      • 一个动态代理类可以代理多个类,只要是实现了同一个接口即可。
11. AOP 11.1 什么是AOP
  • AOP(Aspect Oriented Programming),意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
11.2 AOP在Spring中的作用
  • 提供声明式事务,允许用户自定义切面。
  • 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点,如:日志,安全,缓存,事务等等…
  • 切面(Aspect):横切关注点,被模块化的特殊对象。即,它是一个类。
  • 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
  • 目标(Target):被通知对象。
  • 代理(Proxy):向目标对象应用通知之后创建的对象。
  • 切入点(PointCut):切面通知 执行的 “地点” 的定义。
  • 连接点(JoinPoint):与切入点匹配的执行点。
  • SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:
  • 即Aop在不改变原有代码的情况下,去增加新的功能。
11.3 使用Spring实现AOP
  • 【重点】使用AOP织入,需要导入一个依赖包:
		
			org.aspectj
			aspectjweaver
			1.9.4
		
  1. 方式一:使用Spring的API接口(主要是SpringAPI接口实现)
  • applicationContext.xml
	
	
	
	
	
	
	
	
		
		
		
		
		
		
		
	
  • MyTest
public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //动态代理,代理的是接口,而不是实现类,要注意!
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();
        userService.select();
    }
}
  1. 方式二:自定义来实现AOP(主要是切面定义)
  • DiyPointCut
package com.zach.diy;

public class DiyPointCut {
    
    public void beforeLog(){
        System.out.println("前log...方法执行前...");
    }
    public void afterLog(){
        System.out.println("后log...方法执行后...");
    }
}
  • applicationContext.xml
	
	
	
		
		
			
			
			
			
			
		
		
	
  1. 方式三:使用注解实现!
	
	
	
	
  • AnnotationPointCut
package com.zach.diy;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

//方式三:使用注解方式实现AOP

@Aspect //标注这个类是一个切面
public class AnnotationPointCut {
    //()中写切入点
    @Before("execution(* com.zach.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("=====方法执行前=====");
    }
    @After("execution(* com.zach.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("=====方法执行后=====");
    }
    //在环绕增强中,我们可以给定一个参数,代表我们要获取的处理切入的点
    @Around("execution(* com.zach.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("n=====方法执行环绕之前=====");
        //获得签名
        Signature signature = jp.getSignature();
        System.out.println("signature:"+ signature);
        //执行方法
        Object proceed = jp.proceed();
        System.out.println("=====方法执行环绕之后=====");
    }
}
  • 控制台输出:
=====方法执行环绕之前=====
signature:void com.zach.service.UserService.add()
=====方法执行前=====
增加一个用户
=====方法执行环绕之后=====
=====方法执行后=====

=====方法执行环绕之前=====
signature:void com.zach.service.UserService.select()
=====方法执行前=====
查询一个用户
=====方法执行环绕之后=====
=====方法执行后=====

Process finished with exit code 0
  • 狂神推荐第二种,因为切入点可以复用。
12. 整合Mybatis

步骤:

  1. 导入相关jar包
  • junit
  • mybatis
  • mysql数据库
  • spring相关的
  • aop织入
  • mybatis-spring【new】
	
		
			junit
			junit
			4.12
			test
		
		
			mysql
			mysql-connector-java
			5.1.47
		
		
			org.mybatis
			mybatis
			3.5.2
		
		
			org.springframework
			spring-webmvc
			5.1.9.RELEASE
		
		
		
			org.springframework
			spring-jdbc
			5.1.9.RELEASE
		
		
			org.aspectj
			aspectjweaver
			1.8.13
		
		
			org.mybatis
			mybatis-spring
			2.0.2
		
		
			org.projectlombok
			lombok
			1.16.10
		
	
  1. 编写配置文件

  2. 测试

12.1 回忆mybatis
  1. 编写实体类
package com.zach.pojo;

import lombok.Data;

@Data
public class User {
    private int id;
    private String name;
    private String pwd;
}
  1. 编写核心配置文件




	
		
	
	
	
	
		
			
			
				
				
				
				
			
		
	
	
	
	
	
		
	
	

  1. 编写接口
package com.zach.mapper;

import com.zach.pojo.User;

import java.util.List;

public interface UserMapper {
    public List selectUser();
}
  1. 编写Mapper.xml




	
		select *
		from user;
	

  • applicationContext.xml


	
	
	
	
	
		
	



  1. 测试
import com.zach.mapper.UserMapper;
import com.zach.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class MyTest {
    @Test
    public void test() throws IOException {
    
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
        for (User user : userMapper.selectUser()) {
            System.out.println(user);
        }
    }
}
12.3 Mybatis-spring(第二种方式)
  • User
package com.zach.pojo;

import lombok.Data;

@Data
public class User {
    private int id;
    private String name;
    private String pwd;
}
  • UserMapper
package com.zach.mapper;

import com.zach.pojo.User;

import java.util.List;

public interface UserMapper {
    public List selectUser();
}
  • UserMapper.xml




	
		select *
		from user;
	
	
	
		insert into user (id, name, pwd)
		values (#{id}, #{name}, #{pwd});
	
	
	
		deleteee
		from user
		where id=#{id};
	

  • UserMapperImpl
package com.zach.mapper;

import com.zach.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{

    @Override
    public List selectUser() {
        User user = new User(5, "王道", "99999");
    
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        
        mapper.addUser(user);
        mapper.deleteUser(5);
        
        return mapper.selectUser();
    }
    
    @Override
    public int addUser(User user) {
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        return mapper.addUser(user);
    }
    
    @Override
    public int deleteUser(int id) {
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        return mapper.deleteUser(id);
    }
}
  • mybatis-config.xml




	
		
	
	
	

  • spring-dao.xml



	
	
	
		
		
		
		
	
	
	
	
		
		
		
		
	
	
	
		
		
	
	
	
	
		
		
	
	
	
	
	
		
		
		
			
			
			
			
			
			
		
	
	
	
	
		
		
	
	

  • applicationContext.xml


	
	
	
	
	
		
	


  • MyTest
import com.zach.mapper.UserMapper;
import com.zach.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
        List userList = userMapper.selectUser();
        for (User user : userList) {
            System.out.println(user);
        }
    }
}
spring事务传播特性:
  • 事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。spring支持7种事务传播行为:
    • propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择。
    • propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。
    • propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。
    • propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。
    • propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
    • propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。
    • propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作
  • Spring 默认 的事务传播行为是 PROPAGATION_REQUIRED,它适合于绝大多数的情况。

 
 

—————— THE END ——————
 
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/992421.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号