本文演示的是Spring中使用AspectJ注解和XML配置两种方式实现AOP
下面是使用AspectJ注解实现AOP的Java Project
首先是位于classpath下的applicationContext.xml文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<? 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 > |
然后是服务层接口以及实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
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注解标注的切入类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
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】------" ); } } |
最后是客户端测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
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文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
<? 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*(..)) --> |
然后是服务层接口以及实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
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中所指定的切入类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
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】------" ); } } |
最后是客户端测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
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" ); } } |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。