spring(二) AOP注入

AOP概念

l  AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码

l  经典应用:事务管理、性能监视、安全检查、缓存 、日志等

l  Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码

l  AspectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入

 

Aop的实现原理

l aop底层将采用代理机制进行实现。

专业术语

1.target:目标类,需要被代理的类。例如:UserService

2.Joinpoint(连接点):所谓连接点是指那些可能被拦截到的方法。例如:所有的方法

3.PointCut 切入点:已经被增强的连接点。例如:addUser()

4.advice 通知/增强,增强代码。例如:after、before

5. Weaving(织入):是指把增强advice应用到目标对象target来创建新的代理对象proxy的过程.

6.proxy 代理类

7. Aspect(切面): 是切入点pointcut和通知advice的结合

       一个线是一个特殊的面。

       一个切入点和一个通知,组成成一个特殊的面。

 

1.execution()  用于描述方法 【掌握】

       语法:execution(修饰符  返回值  包.类.方法名(参数) throws异常)

              修饰符,一般省略

                     public             公共方法

                     *                    任意

              返回值,不能省略

                     void               返回没有值

                     String             返回值字符串

                     *                   任意

              包,[省略]

                     com.itheima.crm                   固定包

                     com.itheima.crm.*.service       crm包下面子包任意 (例如:com.itheima.crm.staff.service)

                     com.itheima.crm..                 crm包下面的所有子包(含自己)

                     com.itheima.crm.*.service..     crm包下面任意子包,固定目录service,service目录任意包

              类,[省略]

                     UserServiceImpl                    指定类

                     *Impl                                   以Impl结尾

                     User*                                   以User开头

                     *                                         任意

              方法名,不能省略

                     addUser                              固定方法

                     add*                                   以add开头

                     *Do                                     以Do结尾

                     *                                         任意

              (参数)

                     ()                                        无参

                     (int)                                     一个整型

                     (int ,int)                               两个

                     (..)                                       参数任意

              throws ,可省略,一般不写。

2.within:匹配包或子包中的方法(了解)

       within(com.itheima.aop..*)

3.this:匹配实现接口的代理对象中的方法(了解)

       this(com.itheima.aop.user.UserDAO)

4.target:匹配实现接口的目标对象中的方法(了解)

       target(com.itheima.aop.user.UserDAO)

5.args:匹配参数格式符合标准的方法(了解)

       args(int,int)

6.bean(id)  对指定的bean所有的方法(了解)

       bean('userServiceId')

=======================================================================================

实例 :AOP基于xml配置开发

UserAOP.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
 5         http://www.springframework.org/schema/beans 
 6         http://www.springframework.org/schema/beans/spring-beans.xsd
 7         http://www.springframework.org/schema/aop 
 8         http://www.springframework.org/schema/aop/spring-aop.xsd"> 
 9     
10     <bean id="aspectUser" class="com.spring_aop1.AspectUser"></bean>
11     <bean id="user" class="com.spring_aop1.User"></bean>
12     
13     <aop:config>
14         <!-- expression="execution(返回值  包名.类名.方法名(参数类型))   id="任意":切入点名  -->
15         <aop:pointcut expression="execution(* com.spring_aop1.*.*(..))" id="myPointcut"/>
16         
17         <aop:aspect ref="aspectUser">
18             <aop:before method="password" pointcut-ref="myPointcut"/>
19             <aop:after-returning method="after" pointcut-ref="myPointcut" returning="obj"/>
20         <!-- <aop:around method="around" pointcut-ref="myPointcut" /> -->
21             <aop:around method="aroundR" pointcut-ref="myPointcut" />
22             
23             <aop:after-throwing method="throwable" pointcut-ref="myPointcut" throwing="e"/>
24         </aop:aspect>
25         
26     </aop:config>
27     
28 </beans>

User.java

 1 package com.spring_aop1;
 2 
 3 public class User {
 4     
 5     private String str;
 6 
 7     public String getStr() {
 8         return str;
 9     }
10     public void setStr(String str) {
11         this.str = str;
12     }
13     
14 
15     public void insert(){
16         System.out.println("insert====ok");
17     }
18     public void delete(){
19         System.out.println("delete====ok");
20     }
21     public void update(){
22         System.out.println("update====ok");
23     }
24     public void selete(){
25         System.out.println("insert====ok");
26     }
27     
28 }

AspectUser.java

 

 1 package com.spring_aop1;
 2 
 3 import org.aspectj.lang.JoinPoint;
 4 import org.aspectj.lang.ProceedingJoinPoint;
 5 
 6 public class AspectUser {
 7     
 8     /**
 9      *  定义一个前置通知
10      * */
11     public void password(){
12         System.out.println("前置通知:密码验证=====成功");
13     }
14     
15     /**
16      *  定义一个后置通知(可得方法返回值)
17      *  @param jp  execution(void com.spring_aop.User.save())
18      *  @param obj 
19      * */
20     public void after(JoinPoint jp,Object obj){
21         String name = jp.getSignature().getName();
22         
23         System.out.println("后置通知:after获取一个返回值类型====切入点");
24         System.out.println("after返回值信息为:"+name);
25     }
26     
27     /**
28      *  定义一个环绕通知
29      *  @param pjp  execution(void com.spring_aop.User.save())
30      * */
31     public void around(ProceedingJoinPoint pjp) throws Throwable{
32         System.out.println("环绕通知:around执行环绕通知前执行");
33         pjp.proceed();
34         System.out.println("环绕通知:around执行环绕通知后执行");
35     }
36     /**
37      *  定义一个环绕通知(可得方法返回值)
38      * @throws Throwable 
39      * */
40     public Object aroundR(ProceedingJoinPoint pjp) throws Throwable{
41         System.out.println("环绕通知:around执行环绕通知前执行");
42         Object obj = pjp.proceed();
43         System.out.println("环绕通知:around执行环绕通知后执行");
44         
45         String s = pjp.getSignature().getName();
46         System.out.println("around返回值的类型:"+obj+"  around返回方法名:"+s);
47         return obj;
48     }
49     
50     /**
51      *  定义一个异常通知(可得方法返回值)
52      * @throws Throwable 
53      * */
54     public void throwable(JoinPoint jp,Throwable e){
55         System.out.println("到我这里来,说明 你发生了异常======");
56     }
57     
58 }

Test.java

 1 package com.spring_aop1;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 public class UserTest {
 7     
 8     public static void main(String[] args) {
 9         
10         String str = "com/spring_aop1/UserAop.xml";
11         ApplicationContext context = new ClassPathXmlApplicationContext(str);
12         
13         User user = (User)context.getBean("user");
14         user.insert();
15         
16     }
17     
18 }

 

 实例 :AOP基于注解开发

UserAOP.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xmlns:aop="http://www.springframework.org/schema/aop" 
 5     xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
 6         http://www.springframework.org/schema/beans 
 7         http://www.springframework.org/schema/beans/spring-beans.xsd
 8         http://www.springframework.org/schema/aop 
 9         http://www.springframework.org/schema/aop/spring-aop.xsd 
10         http://www.springframework.org/schema/context 
11         http://www.springframework.org/schema/context/spring-context.xsd">
12     
13     <!-- 自动扫描 配置  扫描所有注解 :使用注解注入 -->
14     <context:component-scan base-package="com.spring_aop2"></context:component-scan>
15     
16     <!-- 添加AOP的注解扫描 -->
17     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
18 
19     
20 </beans>

 

User.java

 1 package com.spring_aop2;
 2 
 3 import org.springframework.stereotype.Component;
 4 
 5 @Component(value="user")
 6 public class User {
 7     
 8     private String str;
 9 
10     public String getStr() {
11         return str;
12     }
13     public void setStr(String str) {
14         this.str = str;
15     }
16     
17     public void insert(){
18         System.out.println("insert====ok");
19     }
20     public void delete(){
21         System.out.println("delete====ok");
22     }
23     public void update(){
24         System.out.println("update====ok");
25         int i = 1/0;
26     }
27     public void selete(){
28         System.out.println("insert====ok");
29     }
30 
31 }

 

AspectUser.java

 1 package com.spring_aop2;
 2 
 3 import org.aspectj.lang.JoinPoint;
 4 import org.aspectj.lang.ProceedingJoinPoint;
 5 import org.aspectj.lang.annotation.After;
 6 import org.aspectj.lang.annotation.AfterReturning;
 7 import org.aspectj.lang.annotation.AfterThrowing;
 8 import org.aspectj.lang.annotation.Around;
 9 import org.aspectj.lang.annotation.Aspect;
10 import org.aspectj.lang.annotation.Before;
11 import org.aspectj.lang.annotation.Pointcut;
12 import org.springframework.stereotype.Component;
13 
14 @Component("aspectUser") //组件
15 @Aspect  //声明这是一个切面类
16 public class AspectUser {
17     
18     /**
19      *    <aop:pointcut
20      *        expression="execution(* com.spring_aop2.*.*(..))"
21      *    id="myPointcut" />
22      * */
23     @Pointcut("execution(* com.spring_aop2.*.*(..))")
24     private void myPoint(){}
25     
26     /**
27      *  定义一个前置通知
28      * */
29     @Before("execution(* com.spring_aop2.*.*(..))") //指向切入点的Id(私有方法的方法名)
30     public void password(){
31         System.out.println("前置通知:密码验证=====成功");
32     }
33     
34     /**
35      *  定义一个后置通知(可得方法返回值)
36      *  @param jp  execution(void com.spring_aop.User.save())
37      *  @param obj 
38      * */
39     @AfterReturning(value="myPoint()",returning="obj")
40     public void after(JoinPoint jp,Object obj){
41         String name = jp.getSignature().getName();
42         
43         System.out.println("后置通知:获取一个返回值类型====切入点");
44         System.out.println("after返回值信息为:"+name);
45     }
46     
47     /**
48      *  定义一个环绕通知
49      *  @param pjp  execution(void com.spring_aop.User.save())
50      * */
51     @Around("execution(* com.spring_aop.*.*(..))")
52     public void around(ProceedingJoinPoint pjp) throws Throwable{
53         System.out.println("环绕通知:around执行环绕通知前执行");
54         pjp.proceed();
55         System.out.println("环绕通知:around执行环绕通知后执行");
56     }
57     /**
58      *  定义一个环绕通知(可得方法返回值)
59      * @throws Throwable 
60      * */
61     public Object aroundR(ProceedingJoinPoint pjp) throws Throwable{
62         System.out.println("环绕通知:around执行环绕通知前执行");
63         Object obj = pjp.proceed();
64         System.out.println("环绕通知:around执行环绕通知后执行");
65         
66         String s = pjp.getSignature().getName();
67         System.out.println("around返回值的类型:"+obj+"  around返回方法名:"+s);
68         return obj;
69     }
70     
71     /**
72      *  定义一个异常通知(可得方法返回值)
73      * @throws Throwable 
74      * */
75     @AfterThrowing(value="myPoint()",throwing="e")
76     public void throwable(JoinPoint jp,Throwable e){
77         System.out.println("到我这里来,说明 你发生了异常======");
78     }
79     
80 }

 

Test.java

 1 package com.spring_aop2;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 public class UserTest {
 7     
 8     public static void main(String[] args) {
 9         
10         String str = "com/spring_aop2/UserAop.xml";
11         
12         ApplicationContext context = new ClassPathXmlApplicationContext(str);
13         
14         User user = (User)context.getBean("user");
15         user.insert();
16         //user.update();
17 
18         
19     }
20     
21 }

 

posted @ 2018-03-05 14:55  Mr·Liu  阅读(1172)  评论(0编辑  收藏  举报