spring-编程AOP使用

本文详细解析了Spring框架中的AOP(面向切面编程)原理,包括如何通过编程方式配置切面、使用ProxyFactory和ProxyFactoryBean创建代理对象,以及如何在Spring环境中实现方法级别的前置和后置通知。

前言

  • 编程AOP ,编程AOP ,为啥要了解编程AOP呢,因为实际上 我们用的AOP 操作都是基于编程来做的,只是 spring帮你做了一些操作,所以了解编程AOP 实际上对源码的理解还是有一定的作用的,也就明白了源码中 一些 为什么要这么做的理由

配置切面

  • 如果是通过注解配置的话,其实 仅仅配置@Aspect 表示当前类是一个切面类,然后在方法上配置各种通知比如:@Before
  • 这里讲的是编程 AOP 所以就不多说 注解了

ProxyFactory

  • 纯手动的AOP … spring 底层就是这样的,我基本就是直接复制 源码随便改改就好了…
public class ProxyFactoryContext implements ProxyFactoryContextImplements{

    public static void main(String[] args) {

        //创建 代理工厂
        ProxyFactory proxyFactory = new ProxyFactory();
        // proxyFactory.copyFrom(null);
        // 如果是 true  则使用 cglib
        // 如果是 false 则使用 Proxy
        proxyFactory.setProxyTargetClass(false);
        proxyFactory.setInterfaces();
        // 添加(切面)
        proxyFactory.addAdvice((MethodBeforeAdvice) (method, args1, target) -> {
            System.out.println("前置通知");
        });
        // proxyFactory.addAdvisors();
        // 设置 目标 对象
        proxyFactory.setTargetSource(new SingletonTargetSource(new ProxyFactoryContext()));
        proxyFactory.setExposeProxy(true);
        ProxyFactoryContext proxy = (ProxyFactoryContext) proxyFactory.getProxy();
        proxy.log();
        System.out.println(proxy.getClass().getName());
    }

    @Override
    public void log() {
        System.out.println("我是本体方法");
    }
}

ProxyFactoryBean

  • 可以从 spring 容器中获取

配置通知

@Component("beforeAdvice")
//  实现了 MethodBeforeAdvice 表示当前类是一个 方法级别的 前置操作
public class BeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("before advice.");
    }
}

配置类

@Configuration
public class ProxyFactoryConfig {

    @Bean
    public ProxyFactoryBean proxyFactoryBean(ProxyFactoryBeanInterface beanInterface) throws Exception {
        //  继承了: ProxyCreatorSupport
        ProxyFactory factory = new ProxyFactory();
        //  继承了: ProxyCreatorSupport
        ProxyFactoryBean factoryBean = new ProxyFactoryBean();
        //设置要代理的目标类
        factoryBean.setTarget(beanInterface);
        //设置要代理的接口的全限定类名
        factoryBean.setProxyInterfaces(new Class[]{ProxyFactoryBeanInterface.class});
        //设置切面类的类名称,这里会去 spring 容器中找到 这个 Advice
        factoryBean.setInterceptorNames("beforeAdvice");
        // 这里是直接添加...
        factoryBean.addAdvice(new MethodBeforeAdvice (){
            @Override
            public void before(Method method, Object[] objects, Object o) throws Throwable {
                System.out.println("后置1");
            }
        });
        // 如果是 true则使用 cglib
        // 如果是 false 则使用 Proxy的方式
        factoryBean.setProxyTargetClass(true);
        // 简单来说,你可以 在 代理的目标类 获取到 代理对象
        //  这么做有什么好处呢? 例如: A方法 调用B 方法 ,A是增强的但是B不是那此时我们想让B也是增强的如何处理呢
        // 那就可以通过 AopContext.currentProxy()获取到当前代理对象然后进行内部调用即可
        factoryBean.setExposeProxy(true);
        return factoryBean;
    }
}

定义目标类

public interface ProxyFactoryBeanInterface {

    public void add();
    public void delete();
}
@Component
public class ProxyFactoryBeanInterfaceImpl implements ProxyFactoryBeanInterface {

    @Override
    public void add() {
        System.out.println("++++++++++");
    }

    @Override
    public void delete() {
        System.out.println("--------------");
        // 如果单纯的去调用ADD 会发现不是增强的,
        // 但是我们想 让 delete 在调用 add()的时候 add 也是被AOP增强的要如何处理呢?
        ProxyFactoryBeanInterface o =(ProxyFactoryBeanInterface) AopContext.currentProxy();
        o.add();
    }
}

上下文类

@ComponentScan
public class ProxyFactoryContext {


    public static void main(String[] args) {
        AnnotationConfigApplicationContext value = new AnnotationConfigApplicationContext(ProxyFactoryContext.class);
        // getBean(value);
        // getProxyFactoryBean(value);
        // getBeanByFactoryBean(value);
        getThreadLocal(value);
    }

    private static void getThreadLocal(AnnotationConfigApplicationContext value) {
        ProxyFactoryBeanInterface bean = (ProxyFactoryBeanInterface) value.getBean("proxyFactoryBean");
        bean.delete();
        System.out.println(bean.getClass().getName());

    }

    private static void getBeanByFactoryBean(AnnotationConfigApplicationContext value) {
        ProxyFactoryBeanInterface bean = (ProxyFactoryBeanInterface) value.getBean("proxyFactoryBean");
        bean.add();
        System.out.println(bean.getClass().getName());
    }

    /**
     * 通过工厂拿到的Bean
     *
     * @param value
     */
    private static void getProxyFactoryBean(AnnotationConfigApplicationContext value) {
        ProxyFactoryBean bean = value.getBean(ProxyFactoryBean.class);
        Object object = bean.getObject();
        ProxyFactoryBeanInterface anInterface = (ProxyFactoryBeanInterface) object;
        anInterface.add();
    }

    /**
     * 从新去获取 Bean了
     *
     * @param value
     */
    private static void getBean(AnnotationConfigApplicationContext value) {
        ProxyFactoryBeanInterface bean = (ProxyFactoryBeanInterface) value.getBean("proxyFactoryBeanInterfaceImpl");
        bean.add();
    }
}

参考

https://www.jianshu.com/p/b38b1a8cb0a4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值