Spring核心概念之AOP

一、AOP 的概念

AOP(Aspect Oriented Programming)的缩写,面向切面编程,主要作用就是对代码进行增强处理。理解面向切面编程的含义:就是在不改变原有程序的基础上为代码增加新的功能。

实现面向切面编程需要了解两个概念:

>切入点:可以插入增强处理的方法,比如原对象的fun()方法。

>增强处理类型:在原对象fun()方法之前还是之后插入新功能。

二、Spring AOP简单应用

1.新建一个java项目

2.到官网下载Spring AOP和AspectJ框架所需要的jar包,并将下载所需的jar文件添加到项目中。

3.在项目中添加User实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.jbit.fsd.entity;
 
public class User {
 
    private int id;
    private String username;
    public int getId() {
        return id;
    }
    public void setId( int id) {
        this .id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this .username = username;
    }
     
}

4.添加数据访问层接口和实现类,并添加相应的方法

1
2
3
4
5
6
7
8
9
10
11
12
package com.jbit.fsd.dao;
 
import java.util.List;
 
import com.jbit.fsd.entity.User;
// 数据访问层接口
public interface UserDao {
 
    public List<User> getAll();
     
    public void addUser(User user);
}

实现类:

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.jbit.fsd.dao.impl;
 
import java.util.ArrayList;
import java.util.List;
 
import com.jbit.fsd.dao.UserDao;
import com.jbit.fsd.entity.User;
 
public class UserDaoImpl implements UserDao {
 
    @Override
    public List<User> getAll() {
        //操作数据库读到所有数据
        List<User> list= new ArrayList<User>();
        list.add( new User());
        list.add( new User());
        list.add( new User());
        return list;
    }
 
    @Override
    public void addUser(User user) {
        System.out.println( "添加成功" );
    }
 
}

5.添加业务处理层接口和实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.jbit.fsd.service;
 
import java.util.List;
 
import com.jbit.fsd.dao.UserDao;
import com.jbit.fsd.entity.User;
 
public interface UserService {
 
    public List<User> getAll();
     
    public void addUser(User user);
     
     
}

实现类:

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
package com.jbit.fsd.service.impl;
 
import java.util.List;
 
import com.jbit.fsd.dao.UserDao;
import com.jbit.fsd.entity.User;
import com.jbit.fsd.service.UserService;
 
public class UserServiceImpl implements UserService{
    private UserDao dao;
    //通过spring注入进来
    public void setDao(UserDao dao) {
        this .dao = dao;
    }
 
    @Override
    public List<User> getAll() {
        System.out.println( "正在执行添加用户的业务!" );
        return dao.getAll();
    }
 
    @Override
    public void addUser(User user) {<br>                System.out.println( "正在执行添加用户的业务!" );
        dao.addUser(user);
    }
 
}

6.添加AOP增强处理类

1
2
3
4
5
6
7
8
9
10
11
12
package com.jbit.fsd.aop;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
 
public class ServiceLoging {
    private Log log = LogFactory.getLog( this .getClass());
 
    public void beforeService(){
        log.info( "aop方法被调用!" );
    }
}

7.在src目录下新建applicationContext.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
<?xml version= "1.0" encoding= "UTF-8" ?>
 
<!--
  - Application context definition for JPetStore's business layer.
  - Contains bean references to the transaction manager and to the DAOs in
  - dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation" ).
  -->
<beans xmlns= "http://www.springframework.org/schema/beans"
        xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
        <span style= "color: rgb(255, 0, 0);" >xmlns:aop= "http://www.springframework.org/schema/aop" </span>
        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
            <span style= "color: rgb(255, 0, 0);" >http: //www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd</span>
            http: //www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
        <!-- 以面向接口思想编程实现解耦和 -->
    <bean id= "userDao" class = "com.jbit.fsd.dao.impl.UserDaoImpl" >
    </bean>
    <bean id= "userServiceImpl" class = "com.jbit.fsd.service.impl.UserServiceImpl" >
        <property name= "dao" ref= "userDao" ></property>  <!-- 属性注入 -->
    </bean>
    <!-- 配置切面 -->
    <bean id= "serviceLogging" class = "com.jbit.fsd.aop.ServiceLoging" ></bean>
    <aop:config>
        <!-- 配置切入点 -->
        <aop:pointcut expression= "execution(public void  addUser(com.jbit.fsd.entity.User))" id= "servicePointcut" />
        <!-- 将切面和切入点编制在一起-->
        <aop:aspect ref= "serviceLogging" >
            <aop:before method= "beforeService" pointcut-ref= "servicePointcut" />
        </aop:aspect>
    </aop:config>
</beans>

8.main方法测试:

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
package com.jbit.fsd.test;
 
import java.util.List;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import com.jbit.fsd.dao.UserDao;
import com.jbit.fsd.entity.User;
import com.jbit.fsd.printer.Printer;
import com.jbit.fsd.service.UserService;
import com.jbit.fsd.service.impl.UserServiceImpl;
 
public class Test {
 
    /**
      * @param args
      */
    public static void main(String[] args) {
        ApplicationContext ac= new ClassPathXmlApplicationContext( "applicationContext.xml" );
        UserService dao=(UserService) ac.getBean( "userServiceImpl" );
        dao.addUser( new User());
    }
 
}

说明:

1.在.xml文件中需要添加aop命名空间,导入与aop配置相关的标签。

2.AOP相关的配置在<aop:config>标签中,切入点的配置在<aop:pointcut>标签中。

3.execution是切入点的标识符,括号是切入点的表达式,配置需要增强的方法。

4.切入点表达式常用几种模糊匹配方式:

>public * addUser(com.able.entity.User),“*”表示配置所有类型的返回值。

>public void * (com.able.entity.User), "*"代表匹配所有的方法名。

>public void addUser(..),  " .. "表示匹配所有参数个数和类型。

> * com.able.service.*.*( . . ),  表示匹配com.able.service包下面所有类的所有方法。

> * com.able.service . . *(), 表示匹配com.able.service包以及子包下所有类的所有方法。

三、增强处理类型简介

1.前置增强处理

特点:在目标方法前织入增强处理。

<aop:before method="beforeService" poontcut-ref="servicePointcut"/>

如果想在这个方法中获得切入点的信息,使用如下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.jbit.fsd.aop;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
 
public class ServiceLoging {
    private Log log = LogFactory.getLog( this .getClass());
 
    public void beforeService(JoinPoint joinPoint){
        System.out.println( "aop方法被调用" );
        System.out.println( "连接点对象:" +joinPoint.getTarget().getClass().getSimpleName());
        System.out.println( "连接点方法:" +joinPoint.getSignature());
        System.out.println( "连接点方法参数:" +joinPoint.getArgs()[ 0 ]);
         
    }
}

2.后置增强处理

特点:在���标方法正常执行(不出现异常)后织入增强处理。

<aop:after-returning method="afterReturning" pointcut-ref="servicePointcut"/>

如果需要获取返回值,添加returning="returnVal"

<aop:after-returning method="aft" pointcut-ref="ser" returning="returnVal"/>

1
2
3
public void afterService(Object returnVal){
        System.out.println(returnVal);
    }

3.异常增强处理

特点:在目标方法出现异常后织入增强处理。

<aop:after-throwing mehod=" " pointcut-ref=" " throwing ="ex"/>

如果需要获取异常对象才添加throwing="ex"

1
2
3
public void afterThrowing(Exception ex){
        System.out.println(ex.getMessage());
    }

4.最终增强处理

特点:不论方法是否抛异常,都会在目标方法最后织如增强处理,类似与finally。

<aop:after method="after" pointcut-ref="servicePointcut"/>

5.环绕增强处理

特点:在目标方法的前后都可以织入增强处理。

<aop:around method="" pointcut-ref="" />

1
2
3
4
5
6
7
8
9
public Boolean around(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println( "目标方法的参数:" +pjp.getArgs()[ 0 ]);
        Boolean b = null ;
        if ( true ) {
            b = (Boolean) pjp.proceed(pjp.getArgs());
        }
        return b;
         
    }

四、使用AspectJ 简化AOP配置

Spring的AOP配置常有两种方式:

>通过schema形式实现简单AOP配置,也就是上面事例使用方法。

>使用annotation简化AOP配置。

AspectJ是一个面向切面的框架,AspectJ定义了AOP语法。

使用@AspectJ必须使用jdk5.0以上版本。

步骤:

1.编写业务类(与上面方法相同)。

2.编写切面类。

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.jbit.ssh.aop;
 
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
 
@Aspect    //1.通过注解标记一个切面
public class AspectTest {
     
    @Before ( "execution(* com.jbit.ssh.service..*.*(..))" ) //2.定义切点和增强类型(切点表达式)
    public void ba(){  //3.增强处理的fun  4.配置xml
        System.out.println( "前置增强-------" );
    }
    @After ( "execution(* com.jbit.ssh.service..*.*(..))" )
    public void aa(){
        System.out.println( "后置增强------" );
    }
    /**
      * @before表示前置增强
      * @AfterReturning:表示后置增强处理
      * @Around:表示环绕增强处理
      * @AfterThrowing:表示异常增强处理
      * @After:表示最终增强处理
      */
 
}

3.编写配置文件实现AOP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version= "1.0" encoding= "UTF-8" ?>
 
<!--
  - Application context definition for JPetStore's business layer.
  - Contains bean references to the transaction manager and to the DAOs in
  - dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation" ).
  -->
<beans xmlns= "http://www.springframework.org/schema/beans"
        xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
        <span style= "color: rgb(255, 0, 0);" >xmlns:aop= "http://www.springframework.org/schema/aop" </span>
        xmlns:tx= "http://www.springframework.org/schema/tx"
        xmlns:p= "http://www.springframework.org/schema/p"
        xmlns:context= "http://www.springframework.org/schema/context"
        xsi:schemaLocation="
            http: //www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http: //www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
            <span style= "color: rgb(255, 0, 0);" >http: //www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd</span>
            http: //www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd" >
 
     
      <!-- 4 .基于 @AspectJ 切面的驱动器 -->
    <aop:aspectj-autoproxy />
    <bean class = "com.jbit.ssh.aop.AspectTest" ></bean>
</beans>

猜你喜欢

转载自www.linuxidc.com/Linux/2016-07/133259.htm