对于动态代理的记录

文章介绍了如何使用Java动态代理为实现了Calculator接口的类添加日志功能,以及SpringAOP通过注解实现方法调用前的日志记录。在动态代理中,代理对象是基于Calculator接口创建的,因此可以被转换为Calculator类型。而在SpringAOP中,通过组件扫描和开启注解支持,可以在不直接获取目标Bean的情况下,通过Calculator接口获取到带有日志功能的代理Bean。
摘要由CSDN通过智能技术生成
package com.fuze2333.spring.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

public class ProxyFactory {
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    public Object getProxy(){
        //ClassLoader loader        类加载器
        // Class<?>[] interfaces    接口数组
        // InvocationHandler h      执行处理
        ClassLoader loader = ProxyFactory.class.getClassLoader();
        Class<?>[] interfaces = target.getClass().getInterfaces();
        InvocationHandler h = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("日志:方法:" + method.getName() + ",参数:" + Arrays.toString(args));
                Object result = method.invoke(target, args);
                System.out.println("日志:方法:" + method.getName() + ",结果:" + result);
                return result;
            }
        };
        return Proxy.newProxyInstance(loader, interfaces, h);
    }
}

这是为实现了Calculator接口的CalculatorImpl类所创建的动态代理,添加了日志功能

public class ProxyTest {
    @Test
    public void testProxy(){
        ProxyFactory proxyFactory = new ProxyFactory(new CalculatorImpl());
        Calculator proxy = (Calculator) proxyFactory.getProxy();
        proxy.add(1, 2);
    }
}

这是测试方法,用于测试代理

Calculator proxy = (Calculator) proxyFactory.getProxy();

对于这行代码,为什么生成的代理对象不是Calculator类型:

这个代理对象的目标对象是Calculator,代理类和Calculator类实现了相同的接口(见静态代理),所以生成的代理对象必然不是Calculator类型,代理对象实现了什么接口就用什么接口做类型



看到AOP

@Component
@Aspect //切面注解
public class LogAspect {

    @Before("execution(public int com.fuze2333.spring.aop.annotation.CalculatorImpl.add(int, int))")
    public void beforeAdviceMethod(){
        System.out.println("LogAspect,前置通知");
    }
}

这是切面类LogAspect

<!--扫描生成bean-->
    <context:component-scan base-package="com.fuze2333.spring.aop.annotation"></context:component-scan>

<!--开启基于注解的AOP-->
    <aop:aspectj-autoproxy/>

 这是spring里设置bean的xml文件

这个包下的类

 

 

public class AOPTest {
    @Test
    public void testAOPByAnnotation(){
        ApplicationContext ioc = new ClassPathXmlApplicationContext("aop-annotation.xml");
        Calculator bean = ioc.getBean(Calculator.class);
        bean.add(1,2);
    }
}

这是测试

为什么要获取Calculator接口类型的bean:

和动态代理使用接口强转一样,代理类和目标类都实现相同的接口,所以代理类可以通过接口来获取bean(因为目标类被ioc屏蔽,我们是没法获取它的bean的,这样就不会冲突)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值