天津建设合同备案网站,网页设计师培训无锡,app下载软件电脑版,杭州外贸建站文章目录 一、动态代理1.1、ProxyFactory1.2、Advice的分类1.3、Advisor的理解 二、创建代理对象的方式2.1、ProxyFactoryBean2.2、BeanNameAutoProxyCreator2.3、DefaultAdvisorAutoProxyCreator 三、Spring AOP的理解3.1、AOP中的概念3.2、Advice在Spring AOP中对应API3.3、T… 文章目录 一、动态代理1.1、ProxyFactory1.2、Advice的分类1.3、Advisor的理解 二、创建代理对象的方式2.1、ProxyFactoryBean2.2、BeanNameAutoProxyCreator2.3、DefaultAdvisorAutoProxyCreator 三、Spring AOP的理解3.1、AOP中的概念3.2、Advice在Spring AOP中对应API3.3、TargetSource的使用 一、动态代理
通过cglib来实现的代理对象的创建是基于父子类的被代理类UserService是父类代理类是子类代理对象就是代理类的实例对象代理类是由cglib创建的对于程序员来说不用关心。除开cglib技术jdk本身也提供了一种创建代理对象的动态代理机制但是它只能代理接口也就是UserService得先有一个接口才能利用jdk动态代理机制来生成一个代理对象
1.1、ProxyFactory
在Spring中进行了封装封装出来的类叫做ProxyFactory表示是创建代理对象的一个工厂使用起来会比上面的更加方便比如
UserService target new UserService();
ProxyFactory proxyFactory new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvice(new MethodInterceptor() {Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println(before...);Object result invocation.proceed();System.out.println(after...);return result;}
});
UserInterface userService (UserInterface) proxyFactory.getProxy();
userService.test();通过ProxyFactory我们可以不再关系到底是用cglib还是jdk动态代理了ProxyFactory会帮我们去判断如果UserService实现了接口那么ProxyFactory底层就会用jdk动态代理如果没有实现接口就会用cglib技术上面的代码就是由于UserService实现了UserInterface接口所以最后产生的代理对象是UserInterface类型。
1.2、Advice的分类
Before Advice方法之前执行After returning advice方法return后执行After throwing advice方法抛异常后执行After (finally) advice方法执行完finally之后执行这是最后的比return更后Around advice这是功能最强大的Advice可以自定义执行顺序
1.3、Advisor的理解
跟Advice类似的还有一个Advisor的概念一个Advisor是有一个Pointcut和一个Advice组成的通过Pointcut可以指定要需要被代理的逻辑比如一个UserService类中有两个方法按上面的例子这两个方法都会被代理被增强那么我们现在可以通过Advisor来控制到具体代理哪一个方法
二、创建代理对象的方式
2.1、ProxyFactoryBean
Bean
public ProxyFactoryBean userServiceProxy(){UserService userService new UserService();ProxyFactoryBean proxyFactoryBean new ProxyFactoryBean();proxyFactoryBean.setTarget(userService);proxyFactoryBean.addAdvice(new MethodInterceptor() {Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println(before...);Object result invocation.proceed();System.out.println(after...);return result;}});return proxyFactoryBean;
}通过这种方法来定义一个UserService的Bean并且是经过了AOP的。但是这种方式只能针对某一个Bean。它是一个FactoryBean所以利用的就是FactoryBean技术间接的将UserService的代理对象作为了Bean。ProxyFactoryBean还有额外的功能比如可以把某个Advise或Advisor定义成为Bean然后在ProxyFactoryBean中进行设置
Bean
public MethodInterceptor zhouyuAroundAdvise(){return new MethodInterceptor() {Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println(before...);Object result invocation.proceed();System.out.println(after...);return result;}};
}
Bean
public ProxyFactoryBean userService(){UserService userService new UserService();ProxyFactoryBean proxyFactoryBean new ProxyFactoryBean();proxyFactoryBean.setTarget(userService);proxyFactoryBean.setInterceptorNames(zhouyuAroundAdvise);return proxyFactoryBean;
}2.2、BeanNameAutoProxyCreator
ProxyFactoryBean得自己指定被代理的对象那么我们可以通过BeanNameAutoProxyCreator来通过指定某个bean的名字来对该bean进行代理
Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {BeanNameAutoProxyCreator beanNameAutoProxyCreator new BeanNameAutoProxyCreator();beanNameAutoProxyCreator.setBeanNames(userSe*);beanNameAutoProxyCreator.setInterceptorNames(zhouyuAroundAdvise);beanNameAutoProxyCreator.setProxyTargetClass(true);return beanNameAutoProxyCreator;
}2.3、DefaultAdvisorAutoProxyCreator
Bean
public DefaultPointcutAdvisor defaultPointcutAdvisor(){NameMatchMethodPointcut pointcut new NameMatchMethodPointcut();pointcut.addMethodName(test);DefaultPointcutAdvisor defaultPointcutAdvisor new DefaultPointcutAdvisor();defaultPointcutAdvisor.setPointcut(pointcut);defaultPointcutAdvisor.setAdvice(new ZhouyuAfterReturningAdvise());return defaultPointcutAdvisor;
}
Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator newDefaultAdvisorAutoProxyCreator();return defaultAdvisorAutoProxyCreator;
}通过DefaultAdvisorAutoProxyCreator会直接去找所有Advisor类型的Bean根据Advisor中PointCut和Advice信息确定要代理的Bean以及代理逻辑。但是我们发现通过这种方式我们得依靠某一个类来实现定义我们的Advisor或者Advise或者Pointcut那么这个步骤能不能更加简化一点呢 对的通过注解 比如我们能不能只定义一个类然后通过在类中的方法上通过某些注解来定义PointCut以及Advice可以的比如
Aspect
Component
public class ZhouyuAspect {Before(execution(public void com.zhouyu.service.UserService.test()))public void zhouyuBefore(JoinPoint joinPoint) {System.out.println(zhouyuBefore);}
}通过上面这个类我们就直接定义好了所要代理的方法(通过一个表达式)以及代理逻辑被Before修饰的方法简单明了这样对于Spring来说它要做的就是来解析这些注解了解析之后得到对应的Pointcut对象、Advice对象生成Advisor对象扔进ProxyFactory中进而产生对应的代理对象具体怎么解析这些注解就是**EnableAspectJAutoProxy注解**所要做的事情了后面详细分析。
三、Spring AOP的理解
3.1、AOP中的概念
Aspect表示切面比如被Aspect注解的类就是切面可以在切面中去定义Pointcut、Advice等等Join point表示连接点表示一个程序在执行过程中的一个点比如一个方法的执行比如一个异常的处理在Spring AOP中一个连接点通常表示一个方法的执行。Advice表示通知表示在一个特定连接点上所采取的动作。Advice分为不同的类型后面详细讨论在很多AOP框架中包括Spring会用Interceptor拦截器来实现Advice并且在连接点周围维护一个Interceptor链Pointcut表示切点用来匹配一个或多个连接点Advice与切点表达式是关联在一起的Advice将会执行在和切点表达式所匹配的连接点上Introduction可以使用DeclareParents来给所匹配的类添加一个接口并指定一个默认实现Target object目标对象被代理对象AOP proxy表示代理工厂用来创建代理对象的在Spring Framework中要么是JDK动态代理要么是CGLIB代理Weaving表示织入表示创建代理对象的动作这个动作可以发生在编译时期比如Aspejctj或者运行时比如Spring AOP
3.2、Advice在Spring AOP中对应API
上面说到的Aspject中的注解其中有五个是用来定义Advice的表示代理逻辑以及执行时机
BeforeAfterReturningAfterThrowingAfterAround
我们前面也提到过Spring自己也提供了类似的执行实际的实现类 6. 接口MethodBeforeAdvice继承了接口BeforeAdvice 7. 接口AfterReturningAdvice 8. 接口ThrowsAdvice 9. 接口AfterAdvice 10. 接口MethodInterceptor
Spring会把五个注解解析为对应的Advice类 12. BeforeAspectJMethodBeforeAdvice实际上就是一个MethodBeforeAdvice 13. AfterReturningAspectJAfterReturningAdvice实际上就是一个AfterReturningAdvice 14. AfterThrowingAspectJAfterThrowingAdvice实际上就是一个MethodInterceptor 15. AfterAspectJAfterAdvice实际上就是一个MethodInterceptor 16. AroundAspectJAroundAdvice实际上就是一个MethodInterceptor
3.3、TargetSource的使用
在我们日常的AOP中被代理对象就是Bean对象是由BeanFactory给我们创建出来的但是Spring AOP中提供了TargetSource机制可以让我们用来自定义逻辑来创建被代理对象。比如之前所提到的Lazy注解当加在属性上时会产生一个代理对象赋值给这个属性产生代理对象的代码为
protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final
Nullable String beanName) {BeanFactory beanFactory getBeanFactory();Assert.state(beanFactory instanceof DefaultListableBeanFactory,BeanFactory needs to be a DefaultListableBeanFactory);final DefaultListableBeanFactory dlbf (DefaultListableBeanFactory) beanFactory;TargetSource ts new TargetSource() {Overridepublic Class? getTargetClass() {return descriptor.getDependencyType();}Overridepublic boolean isStatic() {return false;}Overridepublic Object getTarget() {SetString autowiredBeanNames (beanName ! null ? new LinkedHashSet(1) : null);Object target dlbf.doResolveDependency(descriptor, beanName,autowiredBeanNames, null);if (target null) {Class? type getTargetClass();if (Map.class type) {return Collections.emptyMap();}else if (List.class type) {return Collections.emptyList();}else if (Set.class type || Collection.class type) {return Collections.emptySet();}throw newNoSuchBeanDefinitionException(descriptor.getResolvableType(),Optional dependency not present for lazy injection point);}if (autowiredBeanNames ! null) {for (String autowiredBeanName : autowiredBeanNames) {if (dlbf.containsBean(autowiredBeanName)) {dlbf.registerDependentBean(autowiredBeanName, beanName);}}}return target;}Overridepublic void releaseTarget(Object target) {}};ProxyFactory pf new ProxyFactory();pf.setTargetSource(ts);Class? dependencyType descriptor.getDependencyType();if (dependencyType.isInterface()) {pf.addInterface(dependencyType);}return pf.getProxy(dlbf.getBeanClassLoader());
}这段代码就利用了ProxyFactory来生成代理对象以及使用了TargetSource以达到代理对象在执行某个方法时调用TargetSource的getTarget()方法实时得到一个被代理对象。