AOP切面编程(动态代理)

Spring框架实现AOP的简单原理

动态代理

JDK实现的动态代理

1.原理

目标类与代理类实现了同一个接口。

2.实现方法

Proxy.newProxyInstance,所需参数有三个:

  1. 类的加载器;动态字节码技术创建class时所需要的。
  2. 目标类实现的接口
  3. 额外功能;
private static void test03() {
    //目标类(接口)
    UserService userService = new UserServiceImpl();
    //创建代理类
    UserService o = (UserService) Proxy.newProxyInstance(
        TestUtl.getClass().getClassLoader(),/*任意一个类的加载器*/
        userService.getClass().getInterfaces(),/*目标类的接口*/
        new InvocationHandler() {//附加功能
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                print("--=前置通知=--");
                Object invoke = null;
                try {//执行目标方法
                    invoke = method.invoke(userService, args);
                } catch (Exception e) {
                    print("!--异常通知!--!" + e.getCause());
                    throw e.getCause();
                }
                print("=--后置通知--=");
                return invoke;
            }
        });
    //通过代理类调用目标方法
    o.login("lalala", "1234");
}

CGlib实现的动态代理

1.原理

代理类是目标类的子类。所以如果目标类用final修饰,或者目标类的方法用final修饰,则被修饰的对象、方法都不能被代理。

2.实现方法

new Enhancer(),所需参数有三个:

  1. 类的加载器;动态字节码技术创建class时所需要的。
  2. 目标类的class对象;
  3. 额外功能;
private static void test04() {
    //目标类(实现类)
    UserServiceImpl userService = new UserServiceImpl();
    //cglib创建代理类
    Enhancer enhancer = new Enhancer();
    enhancer.setClassLoader(ReflectUtl.class.getClassLoader());/*类的加载器*/
    enhancer.setSuperclass(userService.getClass());/*目标类的class对象*/
    enhancer.setCallback(new MethodInterceptor() {/*额外功能*/
        @Override
        public Object intercept(Object o, Method method, Object[] args,
                                MethodProxy methodProxy) throws Throwable {
            //前置通知
            Object ret = null;
            try {
                //ret = method.invoke(userService, args);// 反射调用原始方法
        	ret = methodProxy.invoke(userService, objects); // 非反射调用方法
		//ret = methodProxy.invokeSuper(o, objects); // 调用父类方法,入参变为子类(代理类)
            } catch (Exception e) {
                //异常通知
                throw e.getCause();
            }
            //后置通知
            return ret;
        }
    });
    UserService userServiceProxy = (UserService) enhancer.create();
    userServiceProxy.login("aaa", "123456");
    userServiceProxy.register(new User());
}

AOP的简单原理

BeanPostProcessor是Spring 工厂加工原始对象的主要方法:

实现原理

public class ProxyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[]
                    args) throws Throwable {
                print("--- 前置通知 ---");
                Object ret = null;
                try {
                    ret = method.invoke(bean, args);
                } catch (Exception e) {
                	print("--- 异常通知 ---");
                	throw e.getCause();
                }
                print("--- 后置 ---");
                return ret;
            }
        };
        /*spring默认选择jdk动态代理方式,动态代理方式的选择可通过配置实现,此处不深究。*/
        return Proxy.newProxyInstance(ProxyBeanPostProcessor.class.getClassLoader(),
                        bean.getClass().getInterfaces(), handler);
    }
}

BeanPostProcessor的方法是对容器中所有类进行操作的,所以此处还应有切点的逻辑。用来确定哪些类需要添加哪些额外功能。

配置文件

<bean id="userService" class="com.*.*.UserServiceImpl"/>
<!--1.实现 BeanPostProcessor 进行加工-->
<!--2.配置文件中对 BeanPostProcessor 进行配置-->
<bean id="proxyBeanPostProcessor" class="com.*.*.ProxyBeanPostProcessor"/>
posted @ 2021-05-31 10:27  howard4  阅读(126)  评论(0编辑  收藏  举报