zoukankan      html  css  js  c++  java
  • Java : Spring基础 AOP

    简单的JDK动态代理例子(JDK动态代理是用了接口实现的方式)(ICar是接口, GoogleCar是被代理对象, MyCC是处理方法的类):

    public class TestCar {
        public static void main(String[] args) {
            ICar car = (ICar) Proxy.newProxyInstance(TestCar.class.getClassLoader(), GoogleCar.class.getInterfaces(), new MyCC());
            car.start();
            car.run();
        }
    }
    
    class MyCC implements InvocationHandler {
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getName().equals("start")) {
                System.out.println("do something...");
            }
            method.invoke(new GoogleCar(), args);
            return null;
        }
    }

    ===============================================================================

    简单的cglib动态代理例子(cglib是用了继承的方式实现动态代理):

    public class CglibProxy implements MethodInterceptor {
        private CustomerDao customerDao;
    
        public CglibProxy(CustomerDao customerDao) {
            this.customerDao = customerDao;
        }
    
        public CustomerDao createProxy() {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(customerDao.getClass());// 设置父类
            enhancer.setCallback(this);//设置回调,也就是处理的类,这里因为自身实现了这个接口,重写intercept方法
            return (CustomerDao) enhancer.create();//创建代理对象
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("增强方法...");
            return methodProxy.invokeSuper(o, objects);
        }
    }

    ===============================================================================
    springAOP是基于AspectJ(静态代理)和Cglib(动态代理)的

    专业术语:
    Joinpoint(连接点): 指的是可以被拦截到的点,比如一个类里面有四个方法,这四个方法都可以被拦截并增加功能,这四个方法都叫做连接点.
    Pointcut(切入点): 真正被拦截到的点,如果四个方法只有一个被拦截并增强了, 这个方法就叫切入点.
    Advice(通知/增强): 对一个方法进行增强或者权限校验的方法被称为 Advice. 方法层面的增强(在方法前后增强)
    Introduction(引介): 类层面的增强, 比如动态加个属性,加个方法
    Target: 被增强的对象(被代理的对象).
    Weaving(织入): 将Advice应用到Target的过程,简单来说就是增强或者校验的过程.
    Proxy(代理): 代理对象,生成的代理对象.
    Aspect(切面): 多个通知和多个切入点的组合,称为一个切面.

    spring通知类型:
    前置通知: 在目标方法之前进行操作
    后置通知: 在目标方法之后进行操作
    环绕通知: 在执行之前和之后进行操作
    异常抛出通知: 出现异常的时候进行的操作
    最终通知: 无论代码是否有异常,总会进行操作,相当于finally代码块
    引介通知:.....暂时不了解
    ===============================================================================
    XML方式(其中MyAspectXML是权限校验的类,里面的checkPri是权限校验方法,需要在ProductDaoImpl.save方法前执行):

        <bean id="productDao" class="com.smile.myweb.ProductDaoImpl"/>
        <bean id="myAspectXML" class="com.smile.myweb.MyAspectXML"/>
        <aop:config>
            <aop:pointcut id="pointcut1" expression="execution(* com.smile.myweb.ProductDaoImpl.save(..))"/>
            <aop:aspect ref="myAspectXML">
                <aop:before method="checkPri" pointcut-ref="pointcut1"/>
            </aop:aspect>
        </aop:config>

    ===============================================================================
    注解方式 需要开启配置 <aop:aspectj-autoproxy/>
    然后把需要增强的类和代理类都加入IOC 在代理类上面添加@Aspect注解,在增强上面使用@Before或@AfterReturing等注解,如:

    @Aspect
    public class MyAspectAnno {
        @Before(value = "execution(* com.smile.myweb.OrderDao.save(..))")
        public void before() {
            System.out.println("前置通知~~~");
        }
    }

    @Before 前置通知 例子略

    @AfterReturing 后置通知 后置通知可以接受返回值,使用注解里面的 returning 参数:
    ---------------------------------------------------------------------------------------

        @AfterReturning(value = "execution(* com.smile.myweb.OrderDao.save(..))", returning = "result")
        public void after(Object result) {
            System.out.println("后置通知~~~");
            System.out.println(result);
        }

    @Around 环绕通知
    ------------------------------------------------------------------------------------------

        @Around(value = "execution(* com.smile.myweb.OrderDao.save(..))")
        public void after(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("环绕前~");
            Object object = joinPoint.proceed();// 执行的方法 object为返回值
            System.out.println("环绕后~");
            System.out.println(object);
        }

    @AfterThrowing 异常抛出通知 有异常抛出的时候才会执行:
    -----------------------------------------------------------------------------------------

        @AfterThrowing(value = "execution(* com.smile.myweb.OrderDao.save(..))", throwing = "e")
        public void after(Throwable e){
            System.out.println("异常" + e.getMessage());
        }


    @After 最终通知 例子略

    ========================================================================
    切入点注解: @Pointcut 如果有很多个通知作用于同一个方法,那么只需要声明一个空方法,加上这个注解,然后在别的通知的注解的value值写上 类名.方法名() 就可以了 如:
    -------------------------------------------------------------------------------------------

        @After(value = "MyAspectAnno.pointcut1()")
        public void after(){
            System.out.println("最终通知");
        }
    
        @Pointcut(value = "execution(* com.smile.myweb.OrderDao.save(..))")
        private void pointcut1() {}

     try{

        try{
            //@Before
            method.invoke(..);
        }finally{
            //@After
        }
        //@AfterReturning
    }catch(){
        //@AfterThrowing
    }
  • 相关阅读:
    Java代码输出到txt文件(申请专利贴源码的必备利器)
    Vmware10组建局域网
    Ubuntu14.04更换阿里云源
    Ubuntu16.04如何彻底删除Apache2
    HustOJ平台搭建
    Centos 7 联想Y430P无线网卡驱动安装 过程参考
    Windows远程CentOS桌面
    centos 7 查看系统/硬件信息及运维常用命令+联想Y430P无线网卡驱动安装
    zookeeper工作原理、安装配置、工具命令简介
    centos 7 安装五笔输入法
  • 原文地址:https://www.cnblogs.com/cccy0/p/10313010.html
Copyright © 2011-2022 走看看