标签:的区别 time() 加载 概念 proc tde ati odm 创建
一。概念
1。连接点:应用程序执行期间明确的一个点。比如方法调用,方法调用本身,类初始化和对象实例化。aop插入其他逻辑的地方。
2。通知:在特定连接点执行的代码。
3。切入点:定义何时执行通知的连接点集合。
4。切面:封装在类中的通知和切入点的组合。
5。织入:在适当的位置讲切面插入到应用程序代码中的过程。编译时织入,运行时织入,加载时织入(LTW拦截底层JVM类加载器,在类加载器加载字节码时向其提供织入功能)。
6。目标对象:被代理的对象
7。引入:通过引入其他方法或字段来修改对象结构的过程。
二。类型
1。静态AOP:修改代码,编译时织入。
2。动态AOP:运行时动态织入。spring为所有被通知对象创建代理。
三。spring aop
1。第一部分是AOP内核,提供完全解耦的纯编程AOP功能。比如AOP Alliance接口,定义了一组接口来提供服务。
比如:MethodInvocation接口,用于实现方法调用连接点的环绕通知。
示例。下面是创建AOP代理的纯程序化方法。
//1.创建代理,在调用目标方法的时候实际调用的是这个代理
public class AgentDecorator implements MethodInterceptor{
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.print("James");
object retVal = invocation.proceed();//调用被代理的方法。MethodInvocation封装被调用的方法
System.out.print("!");
return retVal;
}
}
//2.织入目标对象
public class AgentAOPDemo{
public static void main(String... args){
Agent target = new Agent();
ProxyFactory pf = new ProxyFactory();//核心类,整合通知和目标类,
pf.addAdvice(new AgentDecorator());//添加代理类,后台委托给addAdvisor(),创建DefaultPointcutAdvisor实例,并应用于所有方法。
pf.setTarget(target);//设置目标类
Agent proxy = (Agent)pf.getProxy();
target.speak();
proxy.speak();
2。第二部分是spring aop架构
spring AOP的核心架构基于代理
(1)JDK动态代理:目标接口实现接口时调用。
(2)CGLIB代理:目标接口未实现接口时调用。
2.1 Spring中的连接点
只支持方法调用,如果需要其他使用AspectJ.
2.2 Spring中的切面
由实现Advisor接口的实例表示。它有两个子接口:PointcutAdvisor IntroductionAdvisor。
2.3 ProxyFactory类
控制Spring AOP中的织入和代理创建过程,ProxyFactory把代理创建过程委托给DefaultAopProxyFactory的一个实例,而该实例又进一步委托给Cglib2AopProxy或者JdkDynamicAopProxy,具体选择哪个由设置参数控制。
2.4 通知类型
(1)前置通知:实现接口 MethodBeforeAdvice
方法:before(Method method, Object[] args, Object target)
(2)后置返回通知:实现接口AfterReturningAdvice 在连接点的方法调用完成并返回一个值后执行后置返回通知。如果方法抛出异常就不会执行。
方法:afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable
(3)后置通知:实现接口AfterAdvice 仅当被通知方法正常完成时才执行后置通知。及时方法异常也会执行。
(4)环绕通知:实现MethodInterceptor接口。可以指定方法执行时机,也可以绕过。
方法:Object invoke(MethodInvocation invocation) throws Throwable{
//前置处理逻辑
invocation.proceed();调用实际的方法
//后置处理逻辑
}
(5)异常通知:实现接口ThrowsAdvice 在方法调用抛出异常时执行
无方法,实现该接口的类需要设置名称为afterThrowing(Exception ex) throws Throwable 或者 afterThrowing(Method method, Object args, Object target, IllegalArgumentException ex) throws Throwable.
spring在异常通知中寻找的第一个方法是一个或者多个被称为afterThrowing()的公共方法。返回类型不重要,最后为void。
(6)引入通知:实现接口IntroductionInterceptor
三。在spring中使用顾问和切入点
通知(addAdvice)会通知目标函数的全部方法,虽然可用在调用的时候通过类型类判断,但是这种方式不太灵活。为此spring提供了顾问(addAdvisor),顾问和通知的区别是增加了切入点,也就是可以指定哪些方法需要被通知。
PointCut接口
public interface Pointcut{
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
public interface ClassFilter{
boolean matcher(Class<?> clazz);
}
public interface MethodMatcher{
boolean matcher(Method m, Class<?> targetClass);
boolean isRuntime(); false:静态只会调用一次上面的方法 true:动态,先调用一次上面的方法进行静态检查,spring还会在每次方法调用的时候调用下面的方法进行检查。
boolean matcher(Method m, Class<?> targetClass, Object[] args);
}
spring 提供了一下实现了上面接口的抽象类,以方便使用。
1.可用的切入点的实现
(1)使用StaticMethodMatcherPointcut创建静态切入点
实现了MethodMatcher和Pointcut接口
public class SimpleStaticPointcut extends staticMethodMatcherPointcut{
//判断方法
@Override
public boolean matcher(Method method, Class<?> cls){
return ("sing".equals(method.getName()));
}
//判断类
@Override
public ClassFilter getClassFilter(){
return cls->(cls==GoodGuitarist.class);
}
}
创建通知从上面的类型中生成一个通知。SimpleAdvice
调用:
Pointcut pc = new SimpleStaticPointcut();
Advice advice = new SimpleAdvice();
Advisor advisor = new DefaultPointcutAdvisor(pc, advice);//使用切入点和通知生成顾问。
ProxyFactory pf = new ProxyFactory();
pf.setAdvisor(advisor);
pf.setTarvget();
.........
(2)使用DyanmicMethodMatcherPointcut创建动态切入点
方法:
1.matches(Method method, Class<?> cls)先执行
2.matches(Method method, Class<?> cls, Object args)后执行,很明显多了参数,可以通过方法的传入参数进一步过滤。
3.ClassFilter getClassFilter()
(3)使用简单名称匹配 NameMatchMethodPointcut
NameMatchMethodPointcut pc = new NameMatchMethodPointcut();
pc.addMethodName("sing");
...
(4) 用正则表达式 JdkRegexpMethodPointcut
JdkRegexpMethodPointcut pc = new JdkRegexpMethodPointcut();
pc.setPattern(".*sing.*"); 只通知方法名称包含sing的方法。
(5)使用AspectJ切入点表达式 AspectJExpressionPointcut
AspectJExpressionPointcut pc = new AspectJExpressionPointcut();
pc.setExpression("execution(* sing*(..))");
(6)使用注解匹配切入点 @AdviceRequired
在要通知的方法或者类上设置这个注解
AnnotationMatchingPointcut pc = AnnotationMatchingPointcut.forMethodAnnotation(AdviceRequired.class);
标签:的区别 time() 加载 概念 proc tde ati odm 创建
原文地址:https://www.cnblogs.com/fymc/p/11332607.html