zoukankan      html  css  js  c++  java
  • spring源码手写aop

     

    AOP:

          aop切面编程,其实就是spring增强器的一个扩展,就是通过beanPostProcessor的after后置方式实现的,其中在after中把需要的bean通过放射+动态代理完成bean的替换,替换成代理bean。然后通过注册拦截器完成代理方式的执行;

        1、代理对象的创建过程(advice,切面、切点)

        2、通过jdkcglib的方式生产代理对象(通过beanPostProcessor的after后置方式实现)

        3、执行方法回调的时候,会到字节码的文件中,直接找回到DynamicAdviceedInterceptor中的intercept方法,在这里执行

                  4、在执行过程中,会生成之前定义好的通知拦截器,来执行

        Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。

        

    Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。

      JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。

      CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

     

    1、首先要注入 @EnableAspectJAutoProxy

    @EnableAspectJAutoProxy
    @ComponentScan(value = "com.flm")
    public class Config {
    }

    2、创建service

    @Component
    public class UserServiceImpl implements UserService {
        public UserServiceImpl(){
            System.out.println("UserServiceImpl 构造方法 create ......");
        }
    @PostConstruct
    private void rn(){ System.out.println("UserServiceImpl 使用@PostConstruct run... ......"); } @Override public String test(){ System.out.println("aop test 业务逻辑...."); return "OK"; } @Override public void testData() { System.out.println("testData 业务逻辑...."); } }

    3、启动类

    public class APP {
        public static void main(String[] args) {
            //  方式1:指定xml启动
    //         ApplicationContext context = new ClassPathXmlApplicationContext("beans-context-content.xml");
            // 方式二:指定配置类启动
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext (Config.class);
    
            // 在spring容器获取bean
            UserService userService = context.getBean(UserService.class);
            // 执行要aop的接口
            String rt = userService.test();
            System.out.println(rt);
            userService.testData();
        }
    }

    4、自定义aop方法(原理)

    @Component
    public class AopPostProcessor implements BeanPostProcessor {
        // 原理 BeanPostProcessor + jdk动态代理实现
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            // 判断哪个接口需要代理的 ,写死
            if("userServiceImpl".equals(beanName)){
                // 创建代理对象 , JDK代理是依赖接口的,有实现接口的为jdk代理,否则为 cglib代理
                Object proxyInstance = Proxy.newProxyInstance(bean.getClass().getClassLoader(), UserServiceImpl.class.getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object result = null;
                        // 判断哪个方法需要代理使用执行的,现在写死test
                        if("test".equals(method.getName())){
                            // 方法之前执行
                            System.out.println("invoke before ...");
                            // 执行方法
                            result = method.invoke(bean, args);
                            // 方法之后执行
                            System.out.println("invoke after ...:"+result.toString());
                        }
                        // 执行方法 返回结果
                        return result;
                    }
                });
                return proxyInstance;
            }
            return bean;
        }
    }

    最后执行userSerie.test(),aop拦截结果如下

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

    详情源码看这个大神写的

    https://www.cnblogs.com/liuyk-code/p/9886033.html

  • 相关阅读:
    linux系统下抢占式内核与非抢占式内核的区别
    Cache映射
    Delphi利用系统环境变量获取常用系统目录
    visual studio2008中AJAX的安装配置,及错误!
    网站配置工具无法建立与数据库的连接的解决方案
    PowDesigner工具的使用
    近日网站开发收获(一)
    (转载)power designer 12.5和破解补丁下载
    《Sqlserver 之我的新大陆》
    学习之路
  • 原文地址:https://www.cnblogs.com/lemon-flm/p/15357545.html
Copyright © 2011-2022 走看看