昊天

Spring中实现AOP的两种方式

这里演示的是Spring中使用AspectJ注解和XML配置两种方式实现AOP

下面是使用AspectJ注解实现AOP的Java Project

首先是位于classpath下的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.5.xsd  
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd  
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">  
      
    
<!-- 启用AspectJ对Annotation的支持 -->         
    
<aop:aspectj-autoproxy/>  
              
    
<bean id="userManager" class="com.jadyer.annotation.UserManagerImpl"/>  
      
    
<bean id="securityHandler" class="com.jadyer.annotation.SecurityHandler"/>  
</beans>  
<?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.5.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    
    
<!-- 启用AspectJ对Annotation的支持 -->       
    
<aop:aspectj-autoproxy/>
            
    
<bean id="userManager" class="com.jadyer.annotation.UserManagerImpl"/>
    
    
<bean id="securityHandler" class="com.jadyer.annotation.SecurityHandler"/>
</beans>


然后是服务层接口以及实现类

 

package com.jadyer.annotation;  
public interface UserManager {  
    
public void addUser(String username, String password);  
    
public void delUser(int userId);  
    
public String findUserById(int userId);  
    
public void modifyUser(int userId, String username, String password);  
}
  
  
/** 
 * 上面的UserManager是服务层的接口 
 * 下面的UserManagerImpl是服务层接口的实现类 
 
*/
  
  
package com.jadyer.annotation;  
  
public class UserManagerImpl implements UserManager {  
    
public void addUser(String username, String password) {  
        System.out.println(
"------UserManagerImpl.addUser() is invoked------");  
    }
  
  
    
public void delUser(int userId) {  
        System.out.println(
"------UserManagerImpl.delUser() is invoked------");  
    }
  
  
    
public String findUserById(int userId) {  
        System.out.println(
"------UserManagerImpl.findUserById() is invoked------");  
        
return "铁面生";  
    }
  
  
    
public void modifyUser(int userId, String username, String password) {  
        System.out.println(
"------UserManagerImpl.modifyUser() is invoked------");  
    }
  
}
  
package com.jadyer.annotation;
public interface UserManager {
    
public void addUser(String username, String password);
    
public void delUser(int userId);
    
public String findUserById(int userId);
    
public void modifyUser(int userId, String username, String password);
}


/**
 * 上面的UserManager是服务层的接口
 * 下面的UserManagerImpl是服务层接口的实现类
 
*/


package com.jadyer.annotation;

public class UserManagerImpl implements UserManager {
    
public void addUser(String username, String password) {
        System.out.println(
"------UserManagerImpl.addUser() is invoked------");
    }


    
public void delUser(int userId) {
        System.out.println(
"------UserManagerImpl.delUser() is invoked------");
    }


    
public String findUserById(int userId) {
        System.out.println(
"------UserManagerImpl.findUserById() is invoked------");
        
return "铁面生";
    }


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

}

接下来是使用AspectJ注解标注的切入类

package com.jadyer.annotation;  
  
import org.aspectj.lang.annotation.After;  
import org.aspectj.lang.annotation.Aspect;  
import org.aspectj.lang.annotation.Pointcut;  
  
@Aspect  
public class SecurityHandler {  
    
/** 
     * 定义Pointcut 
     * 
@see Pointcut的名称为addAddMethod(),此方法没有返回值和参数 
     * 
@see 该方法就是一个标识,不进行调用 
     
*/
  
    @Pointcut(
"execution(* add*(..))"//匹配所有以add开头的方法   
    private void addAddMethod(){};  
      
    
/** 
     * 定义Advice 
     * 
@see 表示我们的Advice应用到哪些Pointcut订阅的Joinpoint上 
     
*/
  
    
//@Before("addAddMethod()")   
    @After("addAddMethod()")  
    
private void checkSecurity() {  
        System.out.println(
"------【checkSecurity is invoked】------");  
    }
         
}
  

 最后是客户端测试类

 

package com.jadyer.annotation;  
  
import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  
  
/** 
 * Spring对AOP的支持:采用Annotation方式 
 * 
@see ------------------------------------------------------------------------------------- 
 * 
@see Spring提供的AOP功能还是很强大的,支持可配置,它的默认实现使用的就是JDK动态代理 
 * 
@see 使用Spring的AOP不需要继承相关的东西,也不需要实现接口 
 * 
@see 但有个前提条件:由于是JDK动态代理,所以若想生成代理,该类就必须得实现一个接口才行 
 * 
@see 如果该类没有implements接口的话,仍去使用Spring的默认AOP实现时,那么就会出错 
 * 
@see 通常需要生成代理的类都是服务层的类,所以通常都会抽一个接口出来。即养成面向接口编程的习惯 
 * 
@see ------------------------------------------------------------------------------------- 
 * 
@see 采用Annotation方式完成AOP示例的基本步骤,如下 
 * 
@see 1、Spring2.0的依赖包配置。新增Annotation支持 
 * 
@see      * SPRING_HOME//dist//spring.jar 
 * 
@see      * SPRING_HOME//lib//log4j//log4j-1.2.14.jar 
 * 
@see      * SPRING_HOME//lib//jakarta-commons//commons-logging.jar 
 * 
@see      * SPRING_HOME//lib//aspectj//*.jar 
 * 
@see 2、将横切性关注点模块化,建立SecurityHandler.java 
 * 
@see 3、采用注解指定SecurityHandler为Aspect 
 * 
@see 4、采用注解定义Advice和Pointcut 
 * 
@see 5、启用AspectJ对Annotation的支持,并且将目标类和Aspect类配置到IoC容器中 
 * 
@see 6、开发客户端 
 * 
@see ------------------------------------------------------------------------------------- 
 
*/
  
public class Client {  
    
public static void main(String[] args) {  
        ApplicationContext factory 
= new ClassPathXmlApplicationContext("applicationContext.xml");  
        UserManager userManager 
= (UserManager)factory.getBean("userManager");  
        userManager.addUser(
"张起灵""02200059");  
    }
  
}
  

 
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------


下面是使用XML配置文件实现AOP的Java Project

首先是位于src根目录中的applicationContext-cglib.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.5.xsd  
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd  
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">  
              
    
<!-- 强制使用CGLIB代理 -->  
    
<!-- <aop:aspectj-autoproxy proxy-target-class="true"/> -->  
      
    
<bean id="userManager" class="com.jadyer.cglib.UserManagerImpl"/>  
      
    
<bean id="securityHandler" class="com.jadyer.cglib.SecurityHandler"/>  
      
    
<aop:config>  
        
<aop:aspect id="securityAspect" ref="securityHandler">   
            
<aop:pointcut id="addAddMethod" expression="execution(* add*(..))"/>  
            
<aop:before method="checkSecurity" pointcut-ref="addAddMethod"/>  
        
</aop:aspect>  
    
</aop:config>  
</beans>  


<!--
匹配add开头的所有的方法
execution(* add*(..))

匹配com.jadyer.servcices.impl包下的所有的类的所有的方法
execution(* com.jadyer.servcices.impl.*.*(..))

匹配com.jadyer.servcices.impl包下的add或者del开头的所有的方法
execution(* com.jadyer.servcices.impl.*.add*(..)) || execution(* com.jadyer.servcices.impl.*.del*(..))
 -->

然后是服务层接口以及实现类

package com.jadyer.cglib;  
public interface UserManager {  
    
public void addUser(String username, String password);  
    
public void delUser(int userId);  
    
public String findUserById(int userId);  
    
public void modifyUser(int userId, String username, String password);  
}
  
  
/** 
 * 上面的UserManager是服务层接口 
 * 下面的UserManagerImpl是服务层接口的实现类 
 
*/
  
  
package com.jadyer.cglib;  
  
public class UserManagerImpl {   
//implements UserManager {   
    public void addUser(String username, String password) {  
        System.out.println(
"------UserManagerImpl.addUser() is invoked------");  
    }
  
  
    
public void delUser(int userId) {  
        System.out.println(
"------UserManagerImpl.delUser() is invoked------");  
    }
  
  
    
public String findUserById(int userId) {  
        System.out.println(
"------UserManagerImpl.findUserById() is invoked------");  
        
return "张三";  
    }
  
  
    
public void modifyUser(int userId, String username, String password) {  
        System.out.println(
"------UserManagerImpl.modifyUser() is invoked------");  
    }
  
}
  
package com.jadyer.cglib;
public interface UserManager {
    
public void addUser(String username, String password);
    
public void delUser(int userId);
    
public String findUserById(int userId);
    
public void modifyUser(int userId, String username, String password);
}


/**
 * 上面的UserManager是服务层接口
 * 下面的UserManagerImpl是服务层接口的实现类
 
*/


package com.jadyer.cglib;

public class UserManagerImpl 
//implements UserManager {
    public void addUser(String username, String password) {
        System.out.println(
"------UserManagerImpl.addUser() is invoked------");
    }


    
public void delUser(int userId) {
        System.out.println(
"------UserManagerImpl.delUser() is invoked------");
    }


    
public String findUserById(int userId) {
        System.out.println(
"------UserManagerImpl.findUserById() is invoked------");
        
return "张三";
    }


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

}

 
接着是在applicationContext-cglib.xml中所指定的切入类

 

package com.jadyer.cglib;  
  
import org.aspectj.lang.JoinPoint;  
  
/** 
 * 将客户调用信息传递到该Advice中 
 * 
@see 可以在Advice中添加一个JoinPoint参数,取得客户端调用的方法名称及参数值 
 * 
@see 以后纯粹使用AOP去写类似这样东西的情况比较少,我们主要使用Spring提供的事务 
 * 
@see 关于这个,知道即可。下面是示例代码 
 
*/
  
public class SecurityHandler {  
    
private void checkSecurity(JoinPoint joinPoint) {  
        
for (int i=0; i<joinPoint.getArgs().length; i++{  
            System.out.println(joinPoint.getArgs()[i]); 
//获取客户端调用的方法的参数值   
        }
  
        System.out.println(joinPoint.getSignature().getName()); 
//获取客户端调用的方法名称   
        System.out.println("------【checkSecurity is invoked】------");  
    }
  
}
  


最后是客户端测试类

 

package com.jadyer.cglib;  
  
import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  
  
/** 
 * 
@see -------------------------------------------------------------------------------------------------- 
 * 
@see JDK动态代理和CGLIB代理的差别 
 * 
@see 1..JDK动态代理对实现了接口的类进行代理 
 * 
@see 2..CGLIB代理可以对类代理,主要对指定的类生成一个子类。由于是继承,所以目标类最好不要使用final声明 
 * 
@see -------------------------------------------------------------------------------------------------- 
 * 
@see 代理方式的选择 
 * 
@see 1..如果目标对象实现了接口,默认情况下会采用JDK动态代理实现AOP,亦可强制使用CGLIB生成代理实现AOP 
 * 
@see 2..如果目标对象未实现接口,那么必须引入CGLIB,这时Spring会在JDK动态代理和CGLIB代理之间自动切换 
 * 
@see 3..比较鼓励业务对象是针对接口编程的,所以鼓励使用JDK动态代理。因为我们所代理的目标,一般都是业务对象 
 * 
@see -------------------------------------------------------------------------------------------------- 
 * 
@see 使用CGLIG代理的步骤 
 * 
@see 1..新增CGLIB库:SPRING_HOME//lib//cglib//*.jar 
 * 
@see 2..新增配置标签,强制使用CGLIB代理<aop:aspectj-autoproxy proxy-target-class="true"/> 
 * 
@see -------------------------------------------------------------------------------------------------- 
 
*/
  
public class Client {  
    
public static void main(String[] args) {  
        ApplicationContext factory 
= new ClassPathXmlApplicationContext("applicationContext-cglib.xml");  
          
        
//当UserManagerImpl实现了UserManager接口的情况下,这时Spring会自动使用JDK动态代理   
        
//如果项目已经引入cglib库,并在配置文件中强制使用CGLIB代理,此时Spring才会使用CGLIB代理   
        
//UserManager userManager = (UserManager)factory.getBean("userManager");   
          
        
//由于此时的UserManagerImpl并没有实现UserManager接口,所以接收类型就不能再使用UserManager接口   
        
//并且项目中已经引入了cglib库,尽管配置文件中没有强制使用CGLIB代理,但Spring会自动使用CGLIB代理        
        UserManagerImpl userManager = (UserManagerImpl)factory.getBean("userManager");  
          
        userManager.addUser(
"吴三省""02200059");  
    }
  
}
  


 

posted on 2012-04-11 16:49 昊天 阅读(3089) 评论(0)  编辑  收藏 所属分类: java


只有注册用户登录后才能发表评论。


网站导航:
 

导航

<2012年4月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

统计

留言簿(1)

随笔分类

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜