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

Spring AOP面向切面编程

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

Spring AOP面向切面编程

文章目录
  • 一、AOP是什么?
  • 二、AOP关键概念
  • 三、JoinPoint核心方法
  • 四、PointCut切点表达式
  • 五、通知类型
    • 1.前四种通知
    • 2.环绕通知
  • 六、利用注解配置AOP
  • 七、代理模式
    • 1.静态代理
    • 2.动态代理
    • 3.CGLib实现代理类
    • 4.总结


一、AOP是什么?

在不修改源码的情况下对程序行为进行扩展


applicationContext.xml



    
    
    
        
    
    
        
    
    
    
    
        
        
        
        

        
        
        
        
        
        
        
        
            
            

        
    

切面类

//切面类
public class MethodAspect {
    //切面方法,用于扩展额外功能
    //JoinPoint 连接点,通过连接点可以获取目标类/方法的信息
    public void printExecutionTime(JoinPoint joinPoint){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String now = sdf.format(new Date());
        String className = joinPoint.getTarget().getClass().getName();//获取目标类的名称
        String methodName = joinPoint.getSignature().getName();
        System.out.println("---"+now+":"+className+"."+methodName);
    }

}

pom.xml



    4.0.0

    com.imooc.spring
    aop
    1.0-SNAPSHOT
    
        
            aliyun
            aliyun
            https://maven.aliyun.com/repository/public
        
    
    
        
            org.springframework
            spring-context
            5.2.6.RELEASE
        
        
        
            org.aspectj
            aspectjweaver
            1.9.5
        
    

二、AOP关键概念



三、JoinPoint核心方法

//切面类
public class MethodAspect {
    //切面方法,用于扩展额外功能
    //JoinPoint 连接点,通过连接点可以获取目标类/方法的信息
    public void printExecutionTime(JoinPoint joinPoint){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String now = sdf.format(new Date());
        String className = joinPoint.getTarget().getClass().getName();//获取目标类的名称
        String methodName = joinPoint.getSignature().getName();
        System.out.println("---"+now+":"+className+"."+methodName);
        Object[] args = joinPoint.getArgs();
        System.out.println("---->参数个数:"+args.length);
        for(Object arg:args){
            System.out.println("---->参数"+arg);
        }
    }
}
四、PointCut切点表达式

五、通知类型


1.前四种通知

applicationContext.xml



    
    
    
        
    
    
        
    
    
    
    
        
        
        
        

        
        
        
        
        
        
        
        
            
            
            
            
            
        
    

切面类

//切面类
public class MethodAspect {
    //切面方法,用于扩展额外功能
    //JoinPoint 连接点,通过连接点可以获取目标类/方法的信息
    public void printExecutionTime(JoinPoint joinPoint){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        String now = sdf.format(new Date());
        String className = joinPoint.getTarget().getClass().getName();//获取目标类的名称
        String methodName = joinPoint.getSignature().getName();
        System.out.println("---"+now+":"+className+"."+methodName);
        Object[] args = joinPoint.getArgs();
        System.out.println("---->参数个数:"+args.length);
        for(Object arg:args){
            System.out.println("---->参数"+arg);
        }
    }

    public void doAfterReturning(JoinPoint joinPoint,Object ret){
        System.out.println("<----返回后通知"+ret);
    }

    public void doAfter(JoinPoint joinPoint){
        System.out.println("<----触发后置通知");
    }
    public void doAfterThrowing(JoinPoint joinPoint,Throwable th){
        System.out.println("<----异常通知"+th.getMessage());
    }
}
2.环绕通知

applicationContext.xml



    
    
    
        
    
    
        
    

    
    
        
        
            
        
    

MethodChecker

public class MethodChecker {
    public Object check(ProceedingJoinPoint pjp) throws Throwable {
        try {
            long startTime = new Date().getTime();
            Object ret = pjp.proceed();//执行目标方法
            long endTime = new Date().getTime();
            long duration = endTime-startTime;
            if(duration>=1000){
                String className = pjp.getTarget().getClass().getName();
                String methodName = pjp.getSignature().getName();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
                String now = sdf.format(new Date());
                System.out.println("======"+now+":"+className+"."+methodName+"("+duration+"ms)=====");

            }
            return ret;
        } catch (Throwable throwable) {
            throw throwable;
        }
    }
}
六、利用注解配置AOP

applicationContext.xml



    
    
    
    

切面类

@Component //标记当前类为组件
@Aspect //说明当前类是切面类
public class MethodChecker {
    //环绕通知,参数为PointCut切点表达式
    @Around("execution(* com.imooc..*Service.*(..))")
    //ProceedingJoinPoint是JoinPoint的升级版,在原有功能外,还可以控制目标方法是否执行
    public Object check(ProceedingJoinPoint pjp) throws Throwable {
        try {
            long startTime = new Date().getTime();
            Object ret = pjp.proceed();//执行目标方法
            long endTime = new Date().getTime();
            long duration = endTime - startTime; //执行时长
            if(duration >= 1000){
                String className = pjp.getTarget().getClass().getName();
                String methodName = pjp.getSignature().getName();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
                String now = sdf.format(new Date());
                System.out.println("=======" + now + ":" + className + "." + methodName + "(" + duration + "ms)======");
            }
            return ret;
        } catch (Throwable throwable) {
            System.out.println("Exception message:" + throwable.getMessage());
            throw throwable;
        }
    }
}
七、代理模式 1.静态代理



UserService

public interface UserService {
    public void createUser();
}

UserServiceImpl

public class UserServiceImpl implements UserService{
    public void createUser() {
        System.out.println("创建用户业务逻辑");
    }
}

UserServiceProxy

public class UserServiceProxy implements UserService{
    //持有委托类的对象
    private UserService userService;
    public UserServiceProxy(UserService userService){
        this.userService = userService;
    }

    public void createUser() {
        System.out.println("===="+new Date() +"====");
        userService.createUser();
    }
}

Application

public class Application {
    public static void main(String[] args) {
        UserService userService = new UserServiceProxy(new UserServiceImpl());
        userService.createUser();
    }
}
2.动态代理


public class ProxyInvocationHandler implements InvocationHandler {
    private Object target;
    private ProxyInvocationHandler(Object target){
        this.target = target;
    }
    
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(new Date());
        Object ret = method.invoke(target, args);//调用目标方法
        return ret;
    }

    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        ProxyInvocationHandler invocationHandler = new ProxyInvocationHandler(userService);
        //动态创建代理类 必须实现接口才可以运行
        UserService userServiceProxy = (UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(),
                userService.getClass().getInterfaces(),
                invocationHandler);
        userServiceProxy.createUser();

        EmployeeService employeeService = new EmployeeServiceImpl();
        EmployeeService employeeServiceProxy=(EmployeeService)Proxy.newProxyInstance(employeeService.getClass().getClassLoader(),
                employeeService.getClass().getInterfaces(),
                new ProxyInvocationHandler(employeeService));
        employeeServiceProxy.createEmployee();
    }
}
3.CGLib实现代理类


4.总结

如果类实现的了对应的接口,则spring优先选择JDK动态代理,如果没有实现接口,则自动使用CGLib通过继承的方式实现代理类

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

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

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