springAOP--学习和理解--用XML配置的方式完成面向切面编程

版权声明:本文为博主原创文章,经博主允许,可自由共享,尽量不要用于商业用途。 https://blog.csdn.net/matrixbbs/article/details/89083722

1 概念

Spring Framework是一个流行的JAVA开源框架,是一个轻量级的JEE解决方案,可以一站式构建企业级应用。
分层架构
组件化
集成框加

Spring通过四种策略来简化JAVAEE开发:

1 基于POJO的轻量级、最小侵入式开发
2 通过IOC和AOP实现松耦合
3 通过AOP和惯例实现声明式事务编程
4 通过AOP和模板消除样板式代码

这说明AOP的概念非常重要。需要理解,学会使用。

从Spring4.0开始,简化了它的学习过程,基于Spring4.x构建的SpringBoot项目可以极大的简化开发中相关配置的复杂性

Spring整体架构

1 核心容器
2 上下文
3 面向切面
4 DAO,ORM
5 Web模块,MVC框架
6 测试模块

常用依赖

spring-context
spring-core
spring-beans
spring-aop
aopalliance
spring-expression
common-logging
junit

产生Spring容器的方法

用注解方式

//产生容器
ApplicationContext cxt = new AnnotationConfigApplicationContext(XXXXConfig.class);
//获取bean
Hello hello = (Hello)cxt.getBean("hello");

用xml配置方式

//产生容器
ApplicationContext cxt = new ClassPathXmlApplicationContext("classpath:/applicationConfig.xml");
//获取bean
Hello hello = (Hello)cxt.getBean("hello");

AOP===Aspect-oriented Programming面向切面的编程

业务与切面增强方式

核心业务在完成时,会有一些通用的复用的代码,如日志,安全性,异常处理,事务等
这些动作,与业务无关,却为业务模块所共同调用的逻辑或是责任,单独地封装起来,以便于减少系统的重复代码,方便维护,降低模块之间的耦合,并有利于未来的可操作性和可维护性。这些就叫切面。

AOP会把软件系统分为两个部分:核心业务点和横切关注点
横切业务点的特点是
!!! 1 发生在核心业务点的多处
!!! 2 各种都基本相似,如权限,日志,认证,事务处理等

实现AOP的技术原理===代理

1 动态代理技术
2 静态织入的方式

AOP核心概念

切面(Aspect):在哪里做和做什么的集合,是一个整体概念,也就是横切关注点的模块化结果

连接点(JoinPoint):在程序执行过程中某个特定的点,即在哪里做

通知(Advice):即动作,也就是做什么【也就是增强的那一部分动作,或者可增加的那一部分动作,如果是要加日志,就是写日志的动作;如果要做事务,就是开启或是关闭事务的动作】

切入点(Pointcut):匹配连接点的一个判断。一般就是一个签名或是声名。即“在哪里做的集合”。核心知识点是:切点表达式

目标对象(Target Object):即将要被增强的对象或是方法。也就是“对谁做”。

AOP代理(对象)(Proxy):在运行过程中,由AOP框架组装并创建出来的对象,也就是用切面包装以后的目标对象,又叫代理对象,它好象是目标对象,但比目标对象功能更强。

织入(Weaving)切面和原方法,编译,加载和运行的全过程叫织入。

通知的类型

1 前置通知
2 返回后通知
3 抛出异常后通知
4 后通知
5 环绕通知

实例

0 创建项目后的POM依赖

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>



        <!-- AspectJ start-->
        <dependency>
          <groupId>org.aspectj</groupId>
          <!-- runtime包 -->
          <artifactId>aspectjrt</artifactId>
          <version>1.6.11</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <!-- 织入包 -->
          <artifactId>aspectjweaver</artifactId>
          <version>1.6.11</version>
        </dependency>
        <!-- 用于动态代理,基于类的代理 -->
        <dependency>
          <groupId>cglib</groupId>
          <artifactId>cglib</artifactId>
          <version>2.1</version>
        </dependency>
        <!-- AspectJ end-->
        
	</dependencies>

1 音乐会接口

package com.fhzheng.demo.concert;

/**
 * 音乐会表演接口
 * 【这是一个经典的AOP示例,在《Spring实战》中给出来的】
 * @author fhzheng
 *
 */
public interface Performance {

	
	/**
	 * 表演方法
	 */
	void perform();
}

2 音乐会实现类【用于模拟核心业务】

package com.fhzheng.demo.concert;

/**
 * 音乐会具体类
 * @author fhzheng
 *
 */
public class Concert implements Performance {

	@Override
	public void perform() {

		System.out.println("音乐会开始...");

	}

}

3 音乐会观众类【用于模拟横切关注点,即切面】

package com.fhzheng.demo.concert;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

/**
 * 音乐会切面类,观众的核心业务是看表演,但仍然需要进行周边切面任务:如检票,落座,鼓掌,或在不成功的情况下要求退票
 * 用注解的方式可以进行ASPECT
 * 用XML配置的方式也可以进行ASPECT
 * @author fhzheng
 *
 */
//@Aspect
public class Audience {

	/**
	 * 切点定义 或叫 切点签名
	 */
	//@Pointcut("execution(* com.fhzheng.demo.concert.*.*(..))")
	public void perform() {}
	
	/**
	 * 前置通知
	 * 即在具体的方法之前执行
	 */
	//@Before("perform()")
	public void checkIn() {
		System.out.println("验票检票...");
	}
	
	/**
	 * 前置通知
	 * 即在具体的方法之前执行
	 */
	//@Before("perform()")
	public void takeSeats() {
		System.out.println("观众入座...");
	}
	
	/**
	 * 返回通知
	 * 即在具体的方法之后执行
	 */
	//@AfterReturning("perform()")
	public void applause() {
		System.out.println("掌声响起...");
	}
	
	/**
	 * 异常通知
	 * 即在具体的方法出现了异常时执行
	 */
	//@AfterThrowing("perform()")
	public void demandRefund() {
		System.out.println("要求退款...");
	}
}

4 spring核心配置与AOP配置

<?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-4.3.xsd">

    <!-- 开启自动代理 -->
    <aop:aspectj-autoproxy />

    <!-- 注册业务bean和切面 -->
    <bean id ="concert" class="com.fhzheng.demo.concert.Concert"></bean>
    <bean id ="audience" class="com.fhzheng.demo.concert.Audience"></bean>
    
    <!-- 配置切面 -->
    <aop:config>
        <aop:aspect ref="audience">
            <aop:pointcut expression="execution(* com.fhzheng.demo.concert.*.*(..))" id="perform"/>
            <aop:before method="checkIn" pointcut-ref="perform"/>
            <aop:before method="takeSeats" pointcut-ref="perform"/>
            <aop:after-returning method="applause" pointcut-ref="perform"/>
            <aop:after-throwing method="demandRefund" pointcut-ref="perform"/>
        </aop:aspect>
    </aop:config>    
    

</beans>

5 测试

package com.fhzheng.demo;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;

import com.fhzheng.demo.concert.Performance;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringAop1ApplicationTests {

	@Test
	public void contextLoads() {
	}

	@Test
	public void aopTest() {
		ApplicationContext cxt =new  ClassPathXmlApplicationContext("classpath:/applicationContext.xml");
		Performance concert = cxt.getBean(Performance.class);
		concert.perform();
	}
}

后记

和之前的IOC一样,有两种生成容器对象的方式,即
1 可以用注解方式来生成
2 可以用XML配置方式来生成

从理解上来讲,用XML方式更容易理解,初学可以多自己来配置一下,加深理解。
XML配置方式也更容易体现解耦。

猜你喜欢

转载自blog.csdn.net/matrixbbs/article/details/89083722