DefaultAdvisorAdapterRegistry / AdvisorAdapterRegistry
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable { 通知器适配器集合 private final List<AdvisorAdapter> adapters = new ArrayList<>(3); // 默认就支持这几种类型的适配器 public DefaultAdvisorAdapterRegistry() { registerAdvisorAdapter(new MethodBeforeAdviceAdapter()); registerAdvisorAdapter(new AfterReturningAdviceAdapter()); registerAdvisorAdapter(new ThrowsAdviceAdapter()); } 将通知封装为通知器 @Override public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { if (adviceObject instanceof Advisor) { return (Advisor) adviceObject; } if (!(adviceObject instanceof Advice)) { throw new UnknownAdviceTypeException(adviceObject); } Advice advice = (Advice) adviceObject; // 如果是MethodInterceptor类型,就根本不用适配器。DefaultPointcutAdvisor是天生处理这种有连接点得通知器的 if (advice instanceof MethodInterceptor) { // So well-known it doesn't even need an adapter. return new DefaultPointcutAdvisor(advice); } // 这一步很显然了,就是校验看看这个advice是否是我们支持的这些类型(系统默认给出3中,但是我们也可以自己往里添加注册的) for (AdvisorAdapter adapter : this.adapters) { // Check that it is supported. if (adapter.supportsAdvice(advice)) { // 如果是支持的,也是被包装成了一个通用类型的DefaultPointcutAdvisor return new DefaultPointcutAdvisor(advice); } } throw new UnknownAdviceTypeException(advice); } 获得通知器的通知 @Override public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List<MethodInterceptor> interceptors = new ArrayList<>(3); Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { interceptors.add((MethodInterceptor) advice); } // 从所支持的适配器中拿到拦截器通知器 for (AdvisorAdapter adapter : this.adapters) { if (adapter.supportsAdvice(advice)) { // 这一步需要注意:一定要把从适配器中拿到MethodInterceptor类型的通知器 interceptors.add(adapter.getInterceptor(advisor)); } } if (interceptors.isEmpty()) { throw new UnknownAdviceTypeException(advisor.getAdvice()); } return interceptors.toArray(new MethodInterceptor[0]); } 注册通知适配器 @Override public void registerAdvisorAdapter(AdvisorAdapter adapter) { this.adapters.add(adapter); } }
下面看看具体的生成代理的两个方法:getSingletonInstance和newPrototypeInstance
getSingletonInstance:
private synchronized Object getSingletonInstance() { // 如果是单例的,现在这里持有这个缓存 创建国就不会再创建了 if (this.singletonInstance == null) { // 根据设置的targetName,去工厂里拿到这个bean对象(普通Bean被包装成SingletonTargetSource) this.targetSource = freshTargetSource(); // 这一步是如果你手动没有去设置需要被代理的接口,Spring还是会去帮你找看你有没有实现啥接口,然后全部给你代理上。可见Spring的容错性是很强的 if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) { // Rely on AOP infrastructure to tell us what interfaces to proxy. Class<?> targetClass = getTargetClass(); if (targetClass == null) { throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy"); } setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader)); } // Initialize the shared singleton instance. super.setFrozen(this.freezeProxy); // createAopProxy()方法就是父类ProxyCreatorSupport的方法,它的具体原理在推荐的博文里已经讲过了,这里就不鳌诉了 // 其中JdkDynamicAopProxy和CglibAopProxy对getProxy()方法的实现,也请参考前面分析 this.singletonInstance = getProxy(createAopProxy()); } return this.singletonInstance; }
newPrototypeInstance:
多例的生成,基本和单例差不多。只是没有缓存了、然后每次创建得事后都是copy一份配置出来,创建一个代理实例~~~有兴趣的自个看哈~
ProxyFactoryBean脱离IoC容器使用
虽然它大多数都是结合IoC容器一起使用,但是它脱离容器依然是可议单独使用的(毕竟生成代理得核心功能在父类ProxyCreatorSupport上,和容器无关的)。比如如下:
public class Main { public static void main(String[] args) { String pointcutExpression = "execution( int com.fsx.maintest.Person.run() )"; // ============================================================= //因为我们要使用AspectJ,所以此处采用AspectJProxyFactory,当然你也可以使用和容器相关的ProxyFactoryBean ProxyFactoryBean factory = new ProxyFactoryBean(); factory.setTarget(new Person()); //AspectJProxyFactory factory = new AspectJProxyFactory(new Person()); //声明一个aspectj切点,一张切面 AspectJExpressionPointcut cut = new AspectJExpressionPointcut(); cut.setExpression(pointcutExpression); // 设置切点表达式 // 声明一个通知(此处使用环绕通知 MethodInterceptor ) Advice advice = (MethodInterceptor) invocation -> { System.out.println("============>放行前拦截..."); Object obj = invocation.proceed(); System.out.println("============>放行后拦截..."); return obj; }; //切面=切点+通知 // 它还有个构造函数:DefaultPointcutAdvisor(Advice advice); 用的切面就是Pointcut.TRUE,所以如果你要指定切面,请使用自己指定的构造函数 // Pointcut.TRUE:表示啥都返回true,也就是说这个切面作用于所有的方法上/所有的方法 // addAdvice();方法最终内部都是被包装成一个 `DefaultPointcutAdvisor`,且使用的是Pointcut.TRUE切面,因此需要注意这些区别 Advisor advisor = new DefaultPointcutAdvisor(cut, advice); factory.addAdvisor(advisor); //Person p = factory.getProxy(); Person p = (Person) factory.getObject(); // 执行方法 p.run(); p.run(10); p.say(); p.sayHi("Jack"); p.say("Tom", 666); } } class Person { public int run() { System.out.println("我在run..."); return 0; } public void run(int i) { System.out.println("我在run...<" + i + ">"); } public void say() { System.out.println("我在say..."); } public void sayHi(String name) { System.out.println("Hi," + name + ",你好"); } public int say(String name, int i) { System.out.println(name + "----" + i); return 0; } }
输出:
============>放行前拦截... 我在run... ============>放行后拦截... 我在run...<10> 我在say... Hi,Jack,你好 Tom----666
ProxyFactory
它和Spring容器没啥关系,可议直接创建代理来使用:
public static void main(String[] args) { ProxyFactory proxyFactory = new ProxyFactory(new HelloServiceImpl()); // 添加两个Advise,一个匿名内部类表示 proxyFactory.addAdvice((AfterReturningAdvice) (returnValue, method, args1, target) -> System.out.println("AfterReturningAdvice method=" + method.getName())); proxyFactory.addAdvice(new LogMethodBeforeAdvice()); HelloService proxy = (HelloService) proxyFactory.getProxy(); proxy.hello(); } 输出: this is LogMethodBeforeAdvice this is my method~~ AfterReturningAdvice method=hello
很显然它代理的Bean都是new出来的,所以比如HelloServiceImpl就不能和Spring IoC很好的结合了,所以一般都是Spring内部去使用。
public class ProxyFactory extends ProxyCreatorSupport { // 它提供了丰富的构造函数~~~ public ProxyFactory() { } public ProxyFactory(Object target) { setTarget(target); setInterfaces(ClassUtils.getAllInterfaces(target)); } public ProxyFactory(Class<?>... proxyInterfaces) { setInterfaces(proxyInterfaces); } public ProxyFactory(Class<?> proxyInterface, Interceptor interceptor) { addInterface(proxyInterface); addAdvice(interceptor); } public ProxyFactory(Class<?> proxyInterface, TargetSource targetSource) { addInterface(proxyInterface); setTargetSource(targetSource); } // 创建代理的语句:调用父类ProxyCreatorSupport#createAopProxy 此处就不用再解释了 public Object getProxy() { return createAopProxy().getProxy(); } public Object getProxy(@Nullable ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); } // 主义这是个静态方法,可以一步到位,代理指定的接口 public static <T> T getProxy(Class<T> proxyInterface, Interceptor interceptor) { return (T) new ProxyFactory(proxyInterface, interceptor).getProxy(); } public static <T> T getProxy(Class<T> proxyInterface, TargetSource targetSource) { return (T) new ProxyFactory(proxyInterface, targetSource).getProxy(); } // 注意:若调用此方法生成代理,就直接使用的是CGLIB的方式的 public static Object getProxy(TargetSource targetSource) { if (targetSource.getTargetClass() == null) { throw new IllegalArgumentException("Cannot create class proxy for TargetSource with null target class"); } ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setTargetSource(targetSource); proxyFactory.setProxyTargetClass(true); return proxyFactory.getProxy(); } }
原理
由源代码可议看出,ProxyFactory
的原理就是ProxyCreatorSupport#createAopProxy
这个方法,其余的没啥了