一开始接触学习的静态代理 到动态代理 再到如今基于两者的理解之上使用spring来实现aop思想。
一些接触spring实现aop之后的总结:
从底层静态代理代码讲解到动态代理再到aop
静态代理 代理的是一个类
后两者最后要对其代理的都是接口,其反射机制作用。
为什么 动态代理不需要如静态代理新建一个类来让代理类代理,是因为在调用程序中将其需要被代理的类
传递给了。在其中动态生成了代理完成了一系列操作
**AOP(Aspect Oriented Programming)意为:**面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
解耦在于横切关注点:日志 缓存 事务…这些被单独分隔开
比如以下的前置通知和后置通知的编写:
package testAOP;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class Log implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println(o.getClass().getName()+"的"+method.getName()+"方法被执行");
}
}
package testAOP;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class AfterLog implements AfterReturningAdvice {
@Override
public void afterReturning( Object returnValue, Method method, Object[] args, Object target) throws Throwable{
System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行,其返回值是"+returnValue);
}
}
其中一个通知的源码:
public interface AfterReturningAdvice extends AfterAdvice {
/**
* Callback after a given method successfully returned.
* @param returnValue the value returned by the method, if any
* @param method method being invoked
* @param args arguments to the method
* @param target target of the method invocation. May be {@code null}.
* @throws Throwable if this object wishes to abort the call.
* Any exception thrown will be returned to the caller if it's
* allowed by the method signature. Otherwise the exception
* will be wrapped as a runtime exception.
*/
void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable;
}
一些名词的了解:
横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 …
切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。
通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
目标(Target):被通知对象。
代理(Proxy):向目标对象应用通知之后创建的对象。
切入点(PointCut):切面通知 执行的 “地点”的定义。
连接点(JointPoint):与切入点匹配的执行点。
基于定义了一个service接口基础上:
package testAOP;
public class ServiceImpl implements Service{
@Override
public void delete() {
System.out.println("删除一个对象");
}
@Override
public void add() {
System.out.println("增加一个对象");
}
@Override
public void query() {
System.out.println("查找一个对象");
}
@Override
public void update() {
System.out.println("更新一个对象");
}
}
.xml方式编写:
注意约束的引用
<!--接口不用注册bean-->
<bean id="Log" class="testAOP.Log"/><!--这一处就是传入需要被代理的对象-->
<!--是引入的新功能-->
<bean id="AfterLog" class="testAOP.AfterLog"/>
<bean id="ServiceImpl" class="testAOP.ServiceImpl"/>
<aop:config><!--用于完成切面 切点-->
<!-- 切入点 expression:表达式匹配要执行的方法 -->
<aop:pointcut id="pointcut" expression="execution(* testAOP.ServiceImpl.*(..))"/>
<aop:advisor advice-ref="Log" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="AfterLog" pointcut-ref="pointcut"/>
</aop:config>
测试:
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import testAOP.Service;
public class AOP_test {
@Test
public void test()
{
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("aop_test.xml");
Service service=(Service)applicationContext.getBean("ServiceImpl");//
service.delete();
}
}
注意测试类的强转始终是指向的是 接口类型service。
纵观以上的整个流程可以看出——即 Aop 在 不改变原有代码的情况下 , 去增加新的功能 .这就是它的功能,而实现这些底层逻辑就是动态代理。