spring基础知识总结----AOP代理模式的实现

来源:互联网 发布:大数据主要来源于 编辑:程序博客网 时间:2024/06/05 08:36

代理模式
问题的提出:
当项目的一些方法完成后,需要增加一些功能如安全性检查,若在原来方法上增加这些功能,就需要修改源代码。
最好的办法是使用一个程序,完成增加的功能,并能调用原来方法 ,这样就不需要修改原来的代码。该程序就是代理。 spring可以通过增加一个横切性关注点,比如权限验证,日志,安全性检查。

代理原则:可控制原对象,但不会改变原对象的接口
代理的种类:静态代理(能看到的,实际存在的代理类)
动态代理:是在运行期生成出来的
对被代理对象的要求:以实现接口的方式完成方法的创建

静态代理:
代理对象和目标对象有共同的接口,实现了相同的方法,并且代理对象有个属性是目标对象的接口,我们可以通过spring配置或注解注入接口的实现类(真正的目标类),这样我们就可以通过操作代理对象的方法取操作目标对象的方法,比如对其增加安全检查。显示的调用目标类的方法,便实现了静态代理。

动态代理:
目标对象类实现接口,代理对象类实现InvocationHandler接口及其invoke(),并定义立一个目标对象类的引用,建立一个方法newProxy()返回代理对象,这个方法的参数(和目标对象类相同的类装载器,代理对象实现的接口,回调对象)。可以在这个代理对象的类中新增方法(功能),在应用层创建代理对象,调用相应的方法,spring对自动调用invoke(),在这里通过反射执行目标对象的方法,给目标对象的方法增加新的功能(织入),这样会给目标对象的每个方法都会织入。
invoke()方法的参数:代理对象,代理对象相应的方法,方法的参数

public Object invoke(Object proxy, Method method, Object[] args)            throws Throwable {}

1 定义一个目标对象的的引用,保存传递过来的目标对象
2 newProxyInstance(同一个类加载器,同一个接口,目标对象的地址)
3 测试类中创建代理

AOP

 AOP中的术语简介
 Cross cutting concern 横切性关注点—检查安全性 (checkSecurity)
 Aspect 切面(模块化的类–SecurityHandler)
 Advice 横切性关注点的实现–checkSecurity
 Pointcut 应用Advice的过滤条件
 Joinpoint 连接点—织入的点(如adduser(..)方法)
 Weave织入–把关注点的方法应用到目标方法的过程
 Target Object 目标对象
 Proxy 代理对象
 Introduction 在类中动态的增加方法

实现方法
1:Annotation (注解)的方式对AOP的支持
—- SPRING_HOME/lib/aspectj/*.jar
—– 定义切面,@Aspect
—— 定义pointcut(举例:@Pointcut(“execution(* add*(..)) || execution(* del*(..))”)
—— 定义advice(举例:@Before(“allAddMethod()”) )
—— 启用对Annotation的支持,applicationContext.xml中加入
—– 把Aspect和目标对象配置在IOC容器中,applicationContext.xml中
配置切面
<bean id="securityHandler" class="com.bjsxt.spring.SecurityHandler"/>
配置userManager的实现
<bean id="userManager" class="com.bjsxt.spring.UserManagerImpl"/>
这样spring就会自动的创建切面对象,并采用动态代理机制把它自动的应用到目标对象上去(创建动态代理类)
—— 测试

2:配置文件的方式对AOP的支持
—— 引入相关的库
—— 定义切面类
—– applicationContext.xml文件中进行配置

配置文件:<!-- 将对象纳入spring管理使用bean标签 -->
<bean id="securityHandler" class="com.isunnyvinson.spring.SecurityHandler"/>
    <bean id="userManager" class="com.isunnyvinson.spring.UserManagerImpl"/>
    <aop:config>        <aop:aspect id="security" ref="securityHandler">     <!-- 切面类的对象叫做切面,在这里就是security -->            <aop:pointcut id="allAddMethod"                           expression="execution(* com.isunnyvinson.spring.UserManagerImpl.add*(..))"/>            <!-- method=""一定是本切面里面的一个方法    pointcut-ref="allAddMethod",作用于allAddMethod标识的pointcut中-->            <aop:before method="checkSecurity" pointcut-ref="allAddMethod"/>        </aop:aspect>    </aop:config>   

解释:
配置信息创建了切面类对象,由这个对象的注解知道了切面、advise、poincut — 给pointcut标识的方法,织入advise。而织入是在方法执行之前, 要完成织入,必须先创建代理对象 ,使用invoke(),要创建代理对象,必须先创建继承了Invocation接口的类的对象 。
所以,一共创建一下四个对象:切面类对象 目标对象 代理对象 实现了Invocation接口的类对象。

附1:
Aspect默认情况下不用实现接口,但对于目标对象(UserManagerImpl.java),在默认情况下必须实现接口,如果没有实现接口必须引入CGLIB库。一句话总结:目标对象没有实现接口,使用CGLIB代理对象;目标对象实现了接口,使用JDK的动态代理。

附2:
可以通过Advice中添加一个JoinPoint参数,这个值会由spring自动传入,从JoinPoint中可以取得
参数值、方法名等等

    private void checkSecurity(JoinPoint joinPoint) {        Object[] args = joinPoint.getArgs();        for (int i=0; i<args.length; i++) {            System.out.println(args[i]);        }        System.out.println("方法名:  "+joinPoint.getSignature().getName());        System.out.println("----------checkSecurity()---------------");    }
0 0
原创粉丝点击