代理模式:
其实就是使用另外一个对象去执行目标对象需要执行的动作,但是这个动作放在目标对象里面又不太合适,因此此时需要引入代理模式。
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