Spring --12.Spring中AOP编程(XML方式)

版权声明:转载请注明原始链接 https://blog.csdn.net/sswqzx/article/details/83989549

1、AOP入门案例

1.1、创建工程并引入依赖

工程为com.day03

依赖如下:

<!--依赖-->
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>
        <!--log4j-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
        </dependency>
    </dependencies>

1.2、引入applicationContext.xml和log4j.properties

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <!--配置相关类到applicationContext.xml-->
    <bean id="customerDao" class="com.day03.dao.Impl.CustomerDaoImpl"></bean>
    <!--配置切面类到applicationContext.xml-->
    <bean id="aspectXml" class="com.day03.aspect.AspectXml"></bean>

    <!--AOP配置-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pointCut1" expression="execution(* com.day03.dao.Impl.CustomerDaoImpl.save(..))" />

        <!--配置切面 告诉spring框架调用切面类中哪个方法来增强-->
        <aop:aspect ref="aspectXml">
            <aop:before method="writeLog" pointcut-ref="pointCut1" />
        </aop:aspect>
    </aop:config>
</beans>

log4j.properties

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=D:/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=debug, stdout, file

1.3、编写CustomerDao.java接口和CustomerDaoImpl.java实现类

CustomerDao.java接口

package com.day03.dao;

public interface CustomerDao {

	public abstract void save();
	public abstract void delete();
	public abstract void update();
	public abstract void select();
}

CustomerDaoImpl.java

package com.day03.dao.Impl;
import com.day03.dao.CustomerDao;

public class CustomerDaoImpl implements CustomerDao {

	@Override
	public void save() {
		System.out.println("持久层:客户保存。。。。。。。");
	}

	@Override
	public void delete() {
		System.out.println("持久层、删除用户。。。。。");
	}

	@Override
	public void update() {
		System.out.println("持久层、更新用户。。。。。。。。。");
	}

	@Override
	public void select() {
		System.out.println("持久层、查询用户..................");
	}

}

1.4、配置相关类到Spring中

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置相关类到applicationContext.xml-->
    <bean id="customerDao" class="com.day03.dao.Impl.CustomerDaoImpl"></bean>
</beans>

1.5、编写切面类AsptectXml.java并配置切面类到Spring中

AsptectXml.java切面类

package com.day03.aspect;

import org.aspectj.lang.JoinPoint;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 20:26 2018/11/12
 */
public class AspectXml {

    public void writeLog() {
        System.out.println("记录日志。。。。。。");
    }
}

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置相关类到applicationContext.xml-->
    <bean id="customerDao" class="com.day03.dao.Impl.CustomerDaoImpl"></bean>
    <!--配置切面类到applicationContext.xml-->
    <bean id="aspectXml" class="com.day03.aspect.AspectXml"></bean>
</beans>

1.6、配置AOP

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置相关类到applicationContext.xml-->
    <bean id="customerDao" class="com.day03.dao.Impl.CustomerDaoImpl"></bean>
    <!--配置切面类到applicationContext.xml-->
    <bean id="aspectXml" class="com.day03.aspect.AspectXml"></bean>

    <!--AOP配置-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pointCut1" expression="execution(* com.day03.dao.Impl.CustomerDaoImpl.save(..))" />

        <!--配置切面 告诉spring框架调用切面类中哪个方法来增强-->
        <aop:aspect ref="aspectXml">
            <aop:before method="writeLog" pointcut-ref="pointCut1" />
        </aop:aspect>
    </aop:config>
</beans>

1.7、测试类

TestAOP.java

package com.day03.test;

import com.day03.dao.CustomerDao;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 20:54 2018/11/12
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestAOP {

    @Autowired
    private CustomerDao customerDao;

    @Test
    public void test1(){
        customerDao.save();
    }
}

2、Spring中AOP通知类型

前置通知、后置通知、环绕通知、异常通知、最终通知

2.1、前置通知

应用: 权限控制 (权限不足,抛出异常)、 记录方法调用信息日志

2.2、后置通知

特点:在目标方法运行后,返回值后执行增强代码逻辑。

应用场景:与业务相关的,如ATM取款机取款后,自动下发短信。

2.3、环绕通知

特点:目标执行前后,都进行增强(控制目标方法执行)

应用场景:日志、缓存、权限、性能监控、事务管理

增强代码的方法要求:

接受的参数:ProceedingJoinPoint(可执行的连接点)

返回值:Object返回值

抛出Throwable异常。

说明:

ProceedingJoinPoint:表示正在执行的连接点,也就是目标方法

joinpoint.proceed表示调用目标方法

2.4、异常通知

作用:目标代码出现异常,通知执行。记录异常日志、通知管理员(短信、邮件)

应用场景:处理异常(一般不可预知),记录日志

2.5、最终通知

作用:不管目标方法是否发生异常,最终通知都会执行(类似于finally代码功能)

应用场景:释放资源 (关闭文件、 关闭数据库连接、 网络连接、 释放内存对象 )

案例:

CustomerDao.java接口

package com.day03.dao;

public interface CustomerDao {

	public abstract void save();
	public abstract Integer delete();
	public abstract Integer update(int a , int b);
	public abstract void list();
	public abstract void select();
}

CustomerDaoImpl.java实现类

package com.day03.dao.Impl;
import com.day03.dao.CustomerDao;

public class CustomerDaoImpl implements CustomerDao {


	@Override
	public void save() {
		System.out.println("持久层:客户保存。。。。。。。");
	}

	@Override
	public Integer delete() {
		System.out.println("持久层、删除用户。。。。。");
		return 100;
	}

	@Override
	public Integer update(int a, int b) {
		System.out.println("持久层、更新用户。。。。。。。。。");
		Integer c = a + b;
		return c;
	}

	@Override
	public void list() {
		System.out.println("这是一个异常。。。。。");
		//int i = 10/0;
	}

	@Override
	public void select() {
		int i =10/0;
		System.out.println("持久层、查询用户..................");
	}

}

切面类:AspectXml.java

package com.day03.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 20:26 2018/11/12
 */
public class AspectXml {

    //入门案例
    public void writeLog() {
        System.out.println("记录日志。。。。。。");
    }


    //前置通知 权限控制 、权限不足、抛出异常、
    public void before(JoinPoint jp) {
        String username = "rose";
        if (!"admin".equals(username)) {
            throw new RuntimeException("你没有对"+jp.getTarget().getClass().getName()+"类中的"+jp.getSignature().getName()+"没有访问权限");
        }
    }


    //后置通知方法 应用:ATM取款取款后、自动下发短信、参数result:被增强那个方法返回值
    public void afterReturning(JoinPoint jp, Object result){
        System.out.println("你取款"+result+"元");
    }


    //环绕通知方法 、应用、事务处理 proceedingJoinPoint 正在执行的连接点
    //joinPonint表示调用目标方法
    public Object around(ProceedingJoinPoint pjp){
        Object proceed = null;
        System.out.println("开启事务");
        //获取目标方法的参数
        Object[] args = pjp.getArgs();
        try {
             proceed = pjp.proceed(args);
            System.out.println("事务提交");
//            打印目标方法里参数的结果值
            System.out.println(proceed);
        } catch (Throwable throwable) {
            System.out.println("事务回滚");
        }
        return proceed;
    }


    //异常抛出通知
    //作用:目标代码出现异常、通知执行、记录日志、通知管理员
    public void afterThrowing(JoinPoint jp,Throwable ex){
        System.out.println("注意、在"+jp.getTarget().getClass().getName()+"类中"+jp.getSignature().getName()+"方法中发生异常"+ex.getMessage());
    }


    //最终通知:不管目标方法是否发生异常、最终通知都会执行、类似于finally代码功能、
    //应用:释放资源、关闭文件、关闭数据库连接、网络连接、释放内存对象
    public void after(JoinPoint jp){
        System.out.println("开始释放资源、连接类方法为:"+jp.getTarget().getClass().getName()+"方法:"+jp.getSignature().getName() );
    }

}

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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置相关类到applicationContext.xml-->
    <bean id="customerDao" class="com.day03.dao.Impl.CustomerDaoImpl"></bean>
    <!--配置切面类到applicationContext.xml-->
    <bean id="aspectXml" class="com.day03.aspect.AspectXml"></bean>

    <!--AOP配置-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pointCut1" expression="execution(* com.day03.dao.Impl.CustomerDaoImpl.save(..))" />
        <aop:pointcut id="pointCut2" expression="execution(* com.day03.dao.Impl.CustomerDaoImpl.delete(..))"/>
        <aop:pointcut id="pointCut3" expression="execution(* com.day03.dao.Impl.CustomerDaoImpl.update(..))"/>
        <aop:pointcut id="pointCut4" expression="execution(* com.day03.dao.Impl.CustomerDaoImpl.list(..))"/>
        <aop:pointcut id="pointCut5" expression="execution(* com.day03.dao.Impl.CustomerDaoImpl.select(..))"/>
        <!--配置切面 告诉spring框架调用切面类中哪个方法来增强-->
        <aop:aspect ref="aspectXml">
            <aop:before method="before" pointcut-ref="pointCut1" />
            <aop:after-returning method="afterReturning" pointcut-ref="pointCut2" returning="result" />
            <aop:around method="around" pointcut-ref="pointCut3"/>
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointCut4" throwing="ex"/>
            <aop:after method="after" pointcut-ref="pointCut5"/>
        </aop:aspect>
    </aop:config>
</beans>

TestAOP.java测试类

package com.day03.test;

import com.day03.dao.CustomerDao;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * @ Author     :ShaoWei Sun.
 * @ Date       :Created in 20:54 2018/11/12
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestAOP {

    @Autowired
    private CustomerDao customerDao;

    //前置
    @Test
    public void test1(){
        customerDao.save();
    }
    //后置
    @Test
    public void test2(){
        customerDao.delete();
    }

    //环绕
    @Test
    public void test3(){
        customerDao.update(5,8);
    }

    //异常
    @Test
    public void test4(){
        customerDao.list();
    }
    //最终、不管目标方法是否发生异常、最终通知都运行
    @Test
    public void test5(){
        customerDao.select();
    }
}

猜你喜欢

转载自blog.csdn.net/sswqzx/article/details/83989549