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

JAVA-代理模式

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

JAVA-代理模式

一,什么是代理模式:

代理模式(Proxy)是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能,如添加权限,访问控制和审计等功能。代理类能增强委托类的行为,代理类和委托类有共同的父类或父类接口,这也就要求代理类和委托类有相似的行为;

二,静态代理;

1)第一步

public interface IMarry {
    void HappyMarry();
}

2)第二步

public class You implements IMarry{
    @Override
    public void HappyMarry() {
        System.out.println("你结婚了.自己的逻辑");
    }
}

3)第三步

public class Wedding implements IMarry{

    private IMarry you;

    public Wedding(IMarry you) {
        this.you =   you              ;
    }

    @Override
    public void HappyMarry() {
        befor();
        you.HappyMarry();
        after();
    }

    private void befor() {
        System.out.println("结婚前布置现场,结婚前的公共逻辑");
    }

    private void after() {
        System.out.println("结婚后,结算,,结婚后的公共逻辑");
    }
}

4)测试 ,在上述步骤之中主要运用到了java多态的特性,因为增强类和目标类实现了同一接口的方法,在通过调用增强类的构造方法,将目标类的方法变成了统一接口的实现,从而利用多态的特性,给目标类实现了增强。

    public static void main(String[] args) {
       You you = new You();
       Wedding wedding = new Wedding(you);
       wedding.HappyMarry();
}
三,JDK动态代理

相对于静态代理而言,动态代理则更为灵活。因为静态代理是针对某个行为的定制化开发,如,结婚需要增强那代理类和目标类都需要实现结婚的接口,租房那就需要租房的代理类和接口。时间越久代码臃肿。动态代理由java反射机制实现,会动态的创建代理对象,大大提高程序的可扩展性,达到代码通用的目的;

1)第一步,和静态代理一样实现统一接口

2)第二步,编写代理类,通过实现jdk的InvocationHandler,来实现动态代理

3)第三步 调用动态代理实现动态增强

四,CGLIB动态代理(了解-暂无) 五,AOP动态代理添加日志

AOP (Aspect Orient Programming),直译过来就是 面向切面编程。AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面。主要运用于日志记录,性能监控,安全控制,事务处理,等一些公共功能的重复使用的地方

  1. 主要特点:
    降低模块之间的耦合性,达到高类聚,低耦合;
    提高代码的复用性;
    提高系统的扩展性,可以在不影响原功能的情况下增加新功能;

  2. 相关概念:
    连接点(joinPoint): 增强执行的位置(增加代码的位置)。在 SpringAOP中连接点总是方法的调用。
    切入点(PointCut): 可以插入增强处理的连接点,一般可能通过一个表达式来描述。
    切面(Aspect): 切面是通知和切点的结合。
    通知(Advice): AOP 框架中的增强处理。通知描述了切面何时执行以及如何执行增强处理。
    前置增强,后置增强,异常增强,环绕增强
    引入(Introduction):特殊的增强,动态为类增加方法。
    织入(Weaving): 将增强处理添加到目标对象中,并创建一个被增强的对象,这个过程就是织入。织入分 为三种时期;
    编译器:AspectJ
    类加载
    运行期:jdk动态代理(实现接口),CGlib(子类,不能用final)

1)引入AOP的依赖

2)再yml文件中开启aop spring.aop.auto=true

3)Aop代码实现

package za.activti.oa.aspect;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.SourceLocation;
import org.springframework.stereotype.Component;
import java.util.Arrays;

@Slf4j
@Component//需要将切面交友IOC容器管理
@Aspect //声明当前类是个切面类
public class LogCut {
    
    //@Pointcut("execution(* za.activti.oa.service.serviceImpl.*(..))")
    //注意这使用注解的方式
    @Pointcut("@annotation(za.activti.oa.aspect.SysLog)")
    public void cut(){

    }

    
    @Before(value = "cut()")
    public void before(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();
        Signature signature = joinPoint.getSignature();
        Object target = joinPoint.getTarget();
        Object aThis = joinPoint.getThis();
        JoinPoint.StaticPart staticPart = joinPoint.getStaticPart();
        SourceLocation sourceLocation = joinPoint.getSourceLocation();
        String longString = joinPoint.toLongString();
        String shortString = joinPoint.toShortString();
        log.info("【前置通知】" +
                        "args={},signature={},target={},aThis={},staticPart={}," +
                        "sourceLocation={},longString={},shortString={}"
                , Arrays.asList(args), signature, target, aThis, staticPart, sourceLocation, longString, shortString);

    }
    
    @After(value = "cut()")
    public void aspectAfter(JoinPoint joinPoint) {
        log.info("【后置通知】kind={}", joinPoint.getKind());
    }

    
    @AfterReturning(pointcut = "cut()", returning = "result")
    public void aspectAfterReturning(JoinPoint joinPoint, Object result) {
        log.info("【返回通知】,shortString={},result=", joinPoint.toShortString(), result);
    }

    
    @AfterThrowing(pointcut = "cut()", throwing = "ex")
    public void aspectAfterThrowing(JoinPoint jp, Exception ex) {
        String methodName = jp.getSignature().getName();
        if (ex instanceof ArithmeticException) {
            log.info("【异常通知】" + methodName + "方法算术异常(ArithmeticException):" + ex.getMessage());
        } else {
            log.info("【异常通知】" + methodName + "方法异常:" + ex.getMessage());
        }
    }

    
    @Around(value = "cut()")
    public Object handleControllerMethod(ProceedingJoinPoint joinPoint) throws Throwable {

        StopWatch stopWatch = StopWatch.createStarted();
        log.info("【环绕通知】执行接口开始,方法={},参数={} ", joinPoint.getSignature(), Arrays.asList(joinPoint.getArgs()).toString());
        //继续下一个通知或目标方法调用,返回处理结果,如果目标方法发生异常,则 proceed 会抛异常.
        //如果在调用目标方法或者下一个切面通知前抛出异常,则不会再继续往后走.
        Object proceed = joinPoint.proceed(joinPoint.getArgs());

        stopWatch.stop();
        long watchTime = stopWatch.getTime();
        log.info("【环绕通知】执行接口结束,方法={}, 返回值={},耗时={} (毫秒)", joinPoint.getSignature(), proceed, watchTime);
        return proceed;
    }
}

3)自定义注解

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@documented
public @interface SysLog {
    String value() default "";
}

4)自定义注解使用

@PostMapping("/test")
@SysLog("增加测试日志")
public String test(){
	return "ok";
}

5)切入点表达式常用举例

  1. execution(* com.wmx.aspect.EmpServiceImpl.findEmpById(Integer)) 匹配 com.wmx.aspect.EmpService 类中的 findEmpById 方法,且带有一个 Integer 类型参数。

  2. execution(* com.wmx.aspect.EmpServiceImpl.findEmpById(*)) 匹配 com.wmx.aspect.EmpService 类中的 findEmpById 方法,且带有一个任意类型参数。

  3. execution(* com.wmx.aspect.EmpServiceImpl.findEmpById(…)) 匹配 com.wmx.aspect.EmpService 类中的 findEmpById 方法,参数不限。

  4. execution(* grp.basic3.se.service.SEBasAgencyService3.editAgencyInfo(…)) || execution(* grp.basic3.se.service.SEBasAgencyService3.adjustAgencyInfo(…)) 匹配 editAgencyInfo 方法或者 adjustAgencyInfo 方法

  5. execution(* com.wmx.aspect.EmpService.*(…)) 匹配 com.wmx.aspect.EmpService 类中的任意方法

  6. execution(* com.wmx.aspect..(…)) 匹配 com.wmx.aspect 包(不含子包)下任意类中的任意方法

  7. execution(* com.wmx.aspect….(…)) 匹配 com.wmx.aspect 包及其子包下任意类中的任意方法

  8. execution(public *(…)) 执行所有公共方法

  9. execution(* set*(…)) 执行所任意set方法

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

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

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