【Spring】框架学习笔记(AOP篇)

6 篇文章 1 订阅

AOP:面向切面编程

AOP 在 Spring 中的作用:1、提供声明式服务(声明式事务)2、允许用户实现自定义切面

传统的编程模式是纵向编程,扩展性不佳。而发生业务的变动时,需要对整个项目进行修改,且复用性不高。                                                                              

AOP 编程模式是横向编程,可以在不修改原有形态的基础上扩展出新的功能(符合开闭模式原则,对扩展开放,对修改关闭)。

简单来说,AOP实现的是在不改变原有代码的情况下,扩展新的功能(通过代理的方式实现)。故而,使得真实角色处理的业务更加纯粹,不在关注于公共的事情。公共业务由代理来完成,实现了业务的分工。公共业务发生扩展时也变得更加集中和方便。

Spring AOP 就是将公共业务(如:日志,安全业务等)与领域业务相结合。当执行领域业务的时候就会自动将公共业务加进来,从而,实现公共业务的重复利用。以下,以日志业务为例。在具体实现类中的每个方法内都需要日志业务,但是这样存在很大的问题,一旦日志业务发生变更,则需要修改的地方很多。故而,我们可以将日志业务提出来单独写成一个方法。这样的话,每次使用时只需要调用 log 方法即可。然而,这样的方法在不同的类中,仍然需要重复的写 log 方法。于是,我们可以进一步改良,通过将 log 方法抽离出来写成一个单独的类,这样的话,每次使用时只需要调用该类的方法即可使用。这样的做法是否就足够完美了?

事实上,通过这样的方法仍然存在不同领域业务中使用日志业务时需要重复调用的弊端。所以,我们若是想要进一步改良的话,可以使用静态代理,把公共的 log 方法放到代理类中。可以实现公共业务和关注的业务的分离使得扩展性较强并且免去了重复的调用。(通过实现类和代理类均实现同样的接口,然后在代理类中通过构造器将接口或者实现类注入进来,然后就可以在代理类的方法实现中增加一些自己的逻辑。)但是很明显,静态代理中,一个代理类只能对一个领域业务接口的实现类进行包装,如果有多个领域业务接口的话就要定义很多实现类和代理类才行。这个时候,就需要用到动态代理技术了。(Spring已经将动态代理封装,可以使用其提供的 API 来实现)。

1、通过使用 Spring 的 API 来实现 AOP。

public interface UserService {
	public void add();
	public void delete();
	public void search(int a);
	public void update();
}
//实现类
public class UserServiceImpl implements UserService{

	@Override
	public void add() {
		// TODO Auto-generated method stub
		System.out.println("增加用户");
	}

	@Override
	public void delete() {
		// TODO Auto-generated method stub
		System.out.println("删除用户");
	}

	@Override
	public void search(int a) {
		// TODO Auto-generated method stub
		System.out.println("查找用户");
	}

	@Override
	public void update() {
		// TODO Auto-generated method stub
		System.out.println("更新用户");
	}
	
}
//从具体实现类中将日志业务抽离出来,并实现 MethodBeforeAdvice 接口(前置通知)
public class Log implements MethodBeforeAdvice{
	/*
	 * @param method 目标的方法对象(被调用的方法对象)
	 * @param args 被调用的方法参数
	 * @param target 被调用的方法的目标对象
	 * */
	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println(target.getClass().getName()+
				"的"+method.getName()+"被执行");
		
		
	}
}
//配置文件
<?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-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="userService" class="com.service.impl.UserServiceImpl"/>
    <bean id="log" class="com.log.Log"/>
    <aop:config>
        <!-- 第一个*是返回值,第二个是路径名称(*表示该路径下的所有),(..)表示所有参数数据类型 -->
    	<aop:pointcut expression="execution(* com.service.impl.*.*(..))" id="pointcut"/>
    	<aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
    </aop:config>
</beans>
//测试类
public class Test {
	public static void main(String[] args) {
		ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
		UserService userService=(UserService)context.getBean("userService");
		userService.add();
	}
}

 2、通过自定义类来实现 AOP(测试类、实现类等同上)

//自定义类
public class Log {
	
	public void before() {
		System.out.println("-----方法执行前-----");
	}
	public void after() {
		System.out.println("-----方法执行后-----");
	}
}
//配置文件
<?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-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="userService" class="com.service.impl.UserServiceImpl"/>
    <bean id="log" class="com.log.Log"/>
    <aop:config>
    	<!-- 关联log -->
    	<aop:aspect ref="log">
    	    <!-- 切入点 -->
    		<aop:pointcut expression="execution(* com.service.impl.*.*(..))" id="pointcut"/>
    		<aop:before method="before" pointcut-ref="pointcut"/>
    		<aop:after method="after" pointcut-ref="pointcut"/>
    	</aop:aspect>
    </aop:config>
</beans>

 3、使用注解来实现 AOP(测试类、实现类等同上)

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class Log {
	//切入点
	@Before("execution(* com.service.impl.*.*(..))")
	public void before() {
		System.out.println("-----方法执行前-----");
	}
	
	@After("execution(* com.service.impl.*.*(..))")
	public void after() {
		System.out.println("-----方法执行后-----");
	}
	
	@Around("execution(* com.service.impl.*.*(..))")
	public void aroud(ProceedingJoinPoint pj) throws Throwable {
		System.out.println("环绕前");
		System.out.println("方法签名:"+pj.getSignature());
		//执行目标方法
		pj.proceed();
		System.out.println("环绕后");
	}
}
//配置文件
<?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-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="userService" class="com.service.impl.UserServiceImpl"/>
    <bean id="log" class="com.log.Log"/>
    <!-- 自动寻找AOP -->
    <aop:aspectj-autoproxy/>
</beans>

 

 

注:AOP中涉及到的名词解释

关注点:新增加的某个事务,如日志,安全,缓存,异常处理

切面:一个关注点的模块化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值