Spring_02_AOP初级总结

 1.AOP简介

是对OOP编程方式的一种补充。翻译过来为“面向切面编程”。

可以理解为一个拦截器框架,但是这个拦截器会非常武断,如果它拦截一个类,那么它就会拦截这个类中的所有方法。如对一个目标列的代理,增强了目标类的所有方法。

两个解决办法:

1.不优雅的做法:

在添加增强时,根据方法名去判断,是否添加增强,但是这样就得一直去维护这个增强类。

2.面向切面:

将增强类和拦截条件组合在一起,然后将这个切面配置到 ProxyFactory 中,从而生成代理。

二、AOP 和 切面的关系

1.类比于 OOP 和 对象,AOP 和 切面就是这样的一种关系。

2.也可以将 切面 看成是 AOP 的一个工具。

三、几个概念

切面(Advisor):是AOP中的一个术语,表示从业务逻辑中分离出来的横切逻辑,比如性能监控,日志记录,权限控制等。

这些功能都可以从核心的业务逻辑中抽离出去。可以解决代码耦合问题,职责更加单一。封装了增强和切点。

增强(Advice):增强代码的功能的类,横切到代码中。

目标:目标方法(JDK代理)或目标类(CGLIB代理)

代理:JDK代理,CGLIB代理。或是通过 ProxyFactory 类生产。

切点:通过一个条件来匹配要拦截的类,这个条件称为切点。如拦截所有带 Controller 注解的类。增强的条件。

连接点:作为增强方法的入参,可以获取到目标方法的信息。

四、概括为一张图

五、增强

1.Weaving(织入):对方法进行增强

(1)前置增强(BeforeAdvice):在目标方法前调用。

(2)后置增强(AfterAdvice):在目标方法后调用。

(3)环绕增强(AroundAdvice):将 Before 和 After ,甚至抛出增强和返回增强合到一起。

(4)返回增强(AfterReturningAdvice):在方法返回结果后执行,该增强可以接收到目标方法返回结果。

(5)抛出增强(AfterThrowingAdvice):在目标方法抛出对应的类型后执行,可以接收到对应的异常信息。

2.Introduction(引入):对类进行增强

(1)引入增强(DeclareParentsAdvice):想让程序在运行的时候动态去实现某个接口,需要引入增强。

2.代码实现 

2.1 AOP的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-3.0.xsd
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
	<!-- xmlns:aop="http://www.springframework.org/schema/aop"  声明要用aop的标签
	 xsi:schemaLocation= aop的标签地址
	 "http://www.springframework.org/schema/aop 
     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"  
	 -->

	<bean id="studentDao" class="org.jsoft.dao.impl.StudentDaoImpl">
	</bean>

	<bean id="studentDaoByMybatis" lazy-init="true"
		class="org.jsoft.dao.impl.StudentDaoByMybatisImpl">
	</bean>

	<bean id="studentService" class="org.jsoft.service.impl.StudentServiceImpl"
		scope="singleton" autowire="byName">
	</bean>

<!-- AOP面向切面的配置 -->
	<!-- 切面对应的类,即切面类 -->
	<bean id="log" class="org.jsoft.log.Log" />
<!--  -->
<!--  -->
	<aop:config>
		<aop:aspect id="myAspect" ref="log"><!-- 切面标签,id标记名称,ref对应的切面类bean的id -->
			<!-- 切点标签,id标记名称 -->
			<aop:pointcut id="businessService"
				expression="execution(* org.jsoft.service..*.*(..))" /><!-- 在该范围的类的所有方法下,执行AOP方法 -->
			<!-- 程序执行前,要执行的方法"before" -->
			<aop:before pointcut-ref="businessService" method="before"/><!--  -->
			<!-- 程序执行后,要执行的方法"after" -->	
			<aop:after pointcut-ref="businessService" method="after"/>
			<!-- 程序整个过程,要执行的方法"around" -->
			<aop:around pointcut-ref="businessService"
				method="around" />
		</aop:aspect>
	</aop:config>

</beans>

2.2 对应切面类Log

package org.jsoft.log;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
//这是一个切面类,已放入IoC容器里.
public class Log implements InvocationHandler{
	private Object obj;
	public void before(){//(1)前置增强,需要实现:MethodBeforeAdvice 接口
		System.out.println("Log.before()");
	}
	public void after(){//(2)后置增强:实现 AfterReturningAdvice 接口
		System.out.println("Log.after()");
	}
    //(3)环绕增强:实现 org.aopalliance.intercept.MethodInterceptor 接口,
	//使用 Object result = methodInvocation.proceed(); 调用目标方法。在目标方法前后添加增强
	public Object around(ProceedingJoinPoint pjp) throws Throwable{
		long l = System.currentTimeMillis();
		Object retVal = pjp.proceed();
		//new Thread().sleep(100);
		System.out.println(System.currentTimeMillis() - l);
		System.out.println("Log.around()");
		return retVal;
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		before();
		Object result = method.invoke(obj, args);
		after();
		return result;
	}
	public Object getObj() {
		return obj;
	}
	public void setObj(Object obj) {
		this.obj = obj;
	}
}

2.3 main测试

import org.springframework.context.support.ClassPathXmlApplicationContext;

/**ApplicationContext 是接口,下面的ClassPathXmlApplicationContext也可以用,后者可以用.close()方法*/
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring/spring.xml"});
Student s = new Student();
s.setName("Joy");
Log log = new Log();
log.setObj(studentService);
//动态代理
//参数1 classLoader类加载器
//interfaces造出来的类要实现那些接口
IStudentService studentServiceProxy = (IStudentService)Proxy.newProxyInstance(Main.class.getClassLoader(), studentService.getClass().getInterfaces(), log);
		
studentServiceProxy.add(s);
context.close();

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值