代理模式:
其实就是使用另外一个对象去执行目标对象需要执行的动作,但是这个动作放在目标对象里面又不太合适,因此此时需要引入代理模式。
Spring中运行代理模式的主要是Spring-Security
例子:目标对象是访问客户端的用户,权限就是切面,权限的认证就是切入点,权限反馈的信息就是通知,用户与权限的关系就是连接点,前置通知、后置通知等都是用户与权限的关系有关。
代理对象的方法=目标对象的目标方法+通知 织入:形成代理对象的方法的过程 注意事项: * 通知实际上是切面中的方法 * 只有符合切入点的目标方法才能加通知 * 连接点是目标对象或者代理对象的其中的方法
* 在jdk中,只要实现了InvocationHandler这个接口的类就是一个拦截器类 * 作用:控制目标对象的目标方法的执行 * @author Administrator * 拦截器的作用: * * 引入类 * 1、引入目标类 * 2、引入安全性的类 * 3、引入日志类 * 4、引入权限类 * * 调用构造函数给对象赋值 * * 在invoke方法中把所以的逻辑结合在一起
* 1、代理对象是由谁产生的?jvm产生的 * 2、代理对象实现了什么接口?实现了SalaryService接口 * 3、代理对象的方法体是什么? * 代理对象的方法体中的内容就是拦截器中invoke方法中的内容 * 4、拦截器中的invoke方法中的method参数是在什么时候赋值的? * 在客户端,代理对象调用方法实际上进入的是拦截器中的invoke方法,这个时候 * 拦截器中的invoke方法中的method参数会被赋值
动态代理: 动态代理分为两种: * jdk的动态代理 * 代理对象和目标对象实现了共同的接口 * 拦截器必须实现InvocationHanlder接口 * cglib的动态代理 * 代理对象是目标对象的子类 * 拦截器必须实现MethodInterceptor接口 * hibernate中session.load采用的是cglib实现的
springAOP:xml * 在配置文件中: * 目标类 <bean id="personDao" class="..PersonDaoImpl"> * 切面 <bean id="transaction" class="..Transaction"> * aop:config <aop:config> //切入点 <aop:pointcut> //切面 <aop:aspect> //配置通知 前置通知 method 切面中的方法 参数为:JoinPoint 从这个参数中可以得到目标方法的信息 point-ref 指向切入点 <aop:before method="" pointcut-ref> 后置通知 method point-ref returning returning="val"和后置通知有一个参数,这个参数可以获取方法的返回值,所以 参数的类型必须为Object,名称和val一致。 如果目标方法遇到异常,则不执行 <aop:after-returning> 最终通知 如果目标方法存在异常,则执行 <aop:after> 环绕通知 控制目标对象的目标方法的执行 环绕通知的方法的参数为:ProceedingJoinPoint ProceedingJoinPoint.proceed 执行目标方法 <aop:around> 异常通知 可以获取目标方法产生的异常信息 throwing="ex"中的ex和异常通知的方法中的参数Throwable的名称保持一致。 <aop:throwing throwing="ex"> </aop:aspect> </aop:config> * 在客户端,如果得到的bean的对象有代理对象,则返回代理对象 * 注意事项 * 如果切入点表达式的类写得不正确,则直接报错,找不到该类 * 如果切入点表达式的方法写错了,则客户端直接返回该bean的对象 * spring的aop的原理可以采用两种形式产生代理对象 * 如果目标类实现接口,则spring会采用jdk动态代理 * 如果目标类没有实现接口,则采用cglib动态代理 * 针对一个目标类,切面可以有很多个
切面的扫描:
1、导入springAOP的注解解析器
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
2、导入类扫描的注解解析器
<context:component-scan base-package="cn.itcast.spring0401.aop.annotation"></context:component-scan>
总结原理: 当启动spring容器的时候,spring容器解析配置文件 * 就会解析到类扫描的注解解析器,会在base-package指定的包及子包中扫描所有的类,看类上是否有@Compontent,@Service,@Controller,@Repository注解, * 如果有,则spring容器创建该类的实例 * 解析到aop的注解解析器,会在纳入spring管理的bean中,看哪个类上面是否有@Aspect注解 * 如果有,则会在方法中查找@Pointcut,就会找到切入点表达式,根据切入点表达式,在纳入spring范围的bean内查找,看哪个bean符合切入点表达式,如果符合则创建代理对象 当客户端访问某一个bean时,如果该bean有代理对象,则返回代理对象,否则返回该bean的对象
* 注解解析器: <aop:aspectj-autoproxy></aop:aspectj-autoproxy> * 支持的注解: @Aspect @Before @After @Pointcut @AfterReturning @Around @AfterThrowing