Spring Aop
Aop面向切面编程
Aop入门动态代理
动态代理,其实与Aop的原理有些相似,可以用动态代理来入门。
什么是动态代理
动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实。代理一般会实现它所表示的实际对象的接口。代理可以访问实际对,不允许直接访问某些类;对访问要做特殊处理客户隐藏了实际对象。客户不知道它是与代理打交道还是与实际对象打交道。
为什么使用动态代理
因为动态代理可以对请求进行任何处理,不允许直接访问某些类;对访问要做特殊处理等都需要使用动态代理进行解决。
动态代理Demo
public interface ISubject {
void dosomething();
}
public class SubjectImpl implements ISubject {
public void dosomething() {
System.out.println("SubjectImpl is working....");
}
}
public class SubjectLoggingProxy {
private ISubject target;
public SubjectLoggingProxy(ISubject target) {
super();
this.target = target;
}
public ISubject getLoggingProxy(){
ISubject proxy= null;
//代理对象由哪一个类加载器负责
ClassLoader loader = target.getClass().getClassLoader();
//代理对象类型
Class[] interfaces = new Class[]{ISubject.class};
//调用代理对象,其中的方法时,执行的代码
InvocationHandler h = new InvocationHandler() {
public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
System.out.println(arg1.getName()+"proxy is working ...");
arg1.invoke(target, arg2);
return 0;
}
};
proxy = (ISubject) Proxy.newProxyInstance(loader, interfaces, h);
return proxy;
}
}
public class Main {
public static void main(String[] args) {
ISubject target = new SubjectImpl();
ISubject proxy = new SubjectLoggingProxy(target).getLoggingProxy();
proxy.dosomething();
}
}
Aop好处
- 每个事物逻辑位于一个位置,代码不分散,便于维护和升级。
- 业务模块更加简洁,只包含核心业务代码。
Aop术语
- 切面 Aspect:横切关注点被模块化后的特殊对象
- 通知 Advice:切面必须完成的方法
- 目标 Target:被通知的对象
- 代理 Proxy:向目标对象应用通知后创建的对象
- 连接点 Joinpoint:程序执行的某个特定位置。类的方法的执行前,执行后等,有两个基本信息,1,方法, 2,相对点,那个方法执行前或后。
- 切点 pointcut:
AspectJ 基于注解或xml实现AOP
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* spring.aop.impl.*.*(String))")
public void beforeSay(JoinPoint joinPoint){
List<Object> list = Arrays.asList(joinPoint.getArgs());
System.out.println(list);
System.out.println(" zhang zui..............");
System.out.println(joinPoint.getSignature().getName());
}
@After("execution(* spring.aop.impl.*.*(String))")
public void afterSay(){
System.out.println(" bi zui..............");
}
}
<context:component-scan base-package="spring.aop.impl"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
其他要点
- @order(int) 可以标记切面的执行顺序
- @Pointcut 来声明切入点表达式,后面的通知直接调用这个被它标记的方法。
基于xml
<!-- 配置AOP -->
<aop:config>
<!-- 配置切点表达式 -->
<aop:pointcut expression="execution(* spring.aop.xml.Subject.*(String))" id="pointcut"/>
<!-- 配置切面及通知 -->
<aop:aspect ref="loggingAspect" order="1">
<aop:before method="beforeSay" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>