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的,这样就不会冲突)