[SXT][WY]Spring07 Spring_AOP示例

===========   用 Annotation的方式 实现 AOP  =================

 

1、spring依赖库
    * SPRING_HOME/dist/spring.jar
    * SPRING_HOME/lib/jakarta-commons/commons-logging.jar
    * SPRING_HOME/lib/log4j/log4j-1.2.14.jar
    * SPRING_HOME/lib/aspectj/*.jar

 

2、采用Aspect定义切面

3、在Aspect定义Pointcut和Advice

4、启用AspectJ对Annotation的支持并且将Aspect类和目标对象配置到Ioc容器中

注意:在这种方法定义中,切入点的方法是不被执行的,它存在的目的仅仅是为了重用切入点
即Advice中通过方法名引用这个切人点

 

AOP术语(对应下面的例子 理解):
    * Cross cutting concern   // 做检查安全性这个需求 就是 一个 横切关注点
    * Aspect    // SecurityHandler类 就是一个 方面aspect
    * Advice    // checkSecurity()方法
    * Pointcut    // add*方法  delete*方法 等等的方法
    * Joinpoint    //
    * Weave    // advice 应用到对象的过程 就叫做weave
    * Target Object    // UserManagerImpl
    * Proxy    // 本例中,从ioc容器中 拿出的usermanager类,就是代理
    * Introduction   // 了解一下,作用是 动态添加方法

 

本节的例子:

 

UserManager.java

public interface UserManager {

    public void addUser(String username, String password);
   
    public void deleteUser(int id);
   
    public void modifyUser(int id, String username, String password);
   
    public String findUserById(int id);
}


UserManagerImpl .java
public class UserManagerImpl implements UserManager {

    public void addUser(String username, String password) {
        System.out.println("-------UserManagerImpl.addUser()----------");
    }

    public void deleteUser(int id) {
        System.out.println("-------UserManagerImpl.deleteUser()----------");
    }

    public String findUserById(int id) {
        System.out.println("-------UserManagerImpl.findUserById()----------");
        return null;
    }

    public void modifyUser(int id, String username, String password) {
        System.out.println("-------UserManagerImpl.modifyUser()----------");
    }
}

 

SecurityHandler.java

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class SecurityHandler {
   
    /**
     * 定义Pointcut,Pointcut的名称就是allAddMethod,此方法不能有返回值和参数,该方法只是一个
     * 标识
     *
     * Pointcut的内容是一个表达式,描述那些对象的那些方法(订阅Joinpoint)
     */
    @Pointcut("execution(* add*(..)) || execution(* del*(..))")

     // 上面 这句话 很重要:意思是

     //  1、在ioc中配置的某一个类,如果这个类中包含有 和 add* 或 del* 匹配的方法,这个类就被代理。

     //  2、在ioc中配置的某一个类,如果这个类中 不包含 add* 或 del* 匹配的方法,ioc就不生成这个类的代理。
    private void allAddMethod(){};
   
    /**
     * 定义Advice,标识在那个切入点何处织入此方法
     */
    @Before("allAddMethod()")
    private void checkSecurity() {
        System.out.println("----------checkSecurity()---------------");
    }   
}

 

Client.java

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Client {

    public static void main(String[] args) {
        BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 这里 从 ioc中拿出的 是 代理
        UserManager userManager = (UserManager)factory.getBean("userManager");
        // 这里 从 ioc中拿出的 是 代理
        UserManager um = (UserManager)factory.getBean("um");
       
        userManager.addUser("张三", "123");
       
        um.addUser("adf", "111");
    }
}

 

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:aop="http://www.springframework.org/schema/aop"
         xmlns:tx="http://www.springframework.org/schema/tx"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
    <aop:aspectj-autoproxy/>
    <bean id="securityHandler" class="test.aop.SecurityHandler"/>          
    <bean id="userManager" class="test.aop.UserManagerImpl"/> //  这里 拿出来就是 代理,因为这个类中,有和pointcut指定的方法 相匹配的方法
    <bean id="um" class="test.aop.UserManagerImpl"/>   // 这里 拿出来 就是 代理,因为这个类中,有和pointcut指定的方法 相匹配的方法
</beans>

 

PS:下面的地方 要好好理解

      @Pointcut("execution(* add*(..)) || execution(* del*(..))")

     // 上面 这句话 很重要:意思是

     //  1、在ioc中配置的某一个类,如果这个类中包含有 和 add* 或 del* 匹配的方法,这个类就被代理。

     //  2、在ioc中配置的某一个类,如果这个类中 不包含 add* 或 del* 匹配的方法,ioc就不生成这个类的代理。

 

 

===========   用 配置文件 的方式 实现 AOP  =================

 

这种方式 和 上一种方式,只有形式的差别,本质完全一样。

看完上个例子,很容易理解这个例子。

 

UserManager.java

UserManagerImpl .java

Client.java

这三个类 不用变。

 

SecurityHandler.java  类变的超级简单,之前annotation的作用 完全 转移到 applicationContext.xml中。

public class SecurityHandler {
   
    private void checkSecurity() {
        System.out.println("----------checkSecurity()---------------");
    }
   
}

 

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:aop="http://www.springframework.org/schema/aop"
         xmlns:tx="http://www.springframework.org/schema/tx"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
   
    <bean id="securityHandler" class="test.aop.SecurityHandler"/>           
   
    <bean id="userManager" class="test.aop.UserManagerImpl"/>
   
    <aop:config>
        <aop:aspect id="security" ref="securityHandler">
            <aop:pointcut id="allAddMethod" expression="execution(* test.aop.UserManagerImpl.add*(..))"/>
            <aop:before method="checkSecurity" pointcut-ref="allAddMethod"/>
        </aop:aspect>
    </aop:config>   

</beans>

 

粗体的部分,对照之前的 annotation 比较。完全 体现 了同样的信息。

 

===========  在advice方法中,如何拿到关于被代理类的更多信息  =================

 

import org.aspectj.lang.JoinPoint;

public class SecurityHandler {
   
    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()---------------");
    }
   
}

 

===========   CGLIB  =================

 

1、被代理的类 实现了某种 接口 的情况下,默认是jdk实现动态代理。

     被代理的类 实现了某种 接口 的情况下,可以强制使用cglib来实现动态代理。

 

2、被代理的类 没有实现某种接口 的情况下,只能使用cglib来生成动态代理。

 

例子1(实现接口时,强制使用cglib代理):

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:aop="http://www.springframework.org/schema/aop"
         xmlns:tx="http://www.springframework.org/schema/tx"
         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

    <aop:aspectj-autoproxy proxy-target-class="true"/>

    <bean id="securityHandler" class="com.bjsxt.spring.SecurityHandler"/>          
   
    <bean id="userManager" class="com.bjsxt.spring.UserManagerImpl"/>
   
    <aop:config>
        <aop:aspect id="security" ref="securityHandler">
            <aop:pointcut id="allAddMethod" expression="execution(* com.bjsxt.spring.UserManagerImpl.add*(..))"/>
            <aop:before method="checkSecurity" pointcut-ref="allAddMethod"/>
        </aop:aspect>
    </aop:config>   
</beans>

 

注意粗体的语句,说明了:代理类的生成 强行指定cglib生成。在client.java类中,断点调试可以清楚的看到效果。

 

例子2(没有实现接口时,spring会自动的使用cglib 来生成代理):

 

这里需要做的 只是 1、把 UserManager.java接口去掉。2、把强行指定那句化删掉  其他不变。

 

spring 回自动判断 使用 jdk动态代理 还是 cglib代理。

 

当然 推荐使用的 还是 jdk动态代理了。

你可能感兴趣的:(spring,AOP,bean,log4j,IOC)