您的位置:首页 > 编程语言 > Java开发

Spring源码阅读(十一)—AOP补充

2017-10-08 15:19 459 查看

Spring源码阅读(十一)—AOP补充

AOP面向切面编程是面向对象编程的一种补充,广泛应用于事务,日志等场景;

AOP实现的关键在于AOP框架能够为目标类创建AOP代理,AOP代理根据创建的形式分为静态代理和动态代理;

静态代理是指在编译期间生成代理类,也成为编译时增强;动态代理是指运行期间借助JDK动态代理或者CGLIB等在内存中临时生成动态代理类,也称为运行时增强;

Spring AOP是运行时增强,AspectJ是编译时增强;Spring AOP为了简化配置使用了和AspectJ一样的注解,但是Spring AOP在运行是依旧是基于动态代理的运行时增强;

个人主页:tuzhenyu’s page

原文地址:Spring源码阅读(十一)—AOP补充

(1)JDK动态代理或CGLIB实现简单的AOP

JDK动态代理实现简单AOP通过定义被代理目标接口,目标实现类,实现了InvacationHandler接口的AOP逻辑实现类,通过Proxy类的newProxyInstance()方法动态生成代理类;

代理目标接口

public interface ForumService {
public void addTopic();
public void removeTopic();
}


代理目标实现类

public class ForumServiceImpl implements ForumService {
public void addTopic(){
System.out.println("in the addTopic");
}

public void removeTopic(){
System.out.println("in the removeTopic");
}
}


代理横切织入代码

public class PerformanceHandler implements InvocationHandler{
private Object target;

public PerformanceHandler(Object target){
this.target = target;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
System.out.println("begin monitor...");
Object obj = method.invoke(target,args);
System.out.println("end monitor...");
return obj;
}
}


代理横测试类

public class Main {
public static void main(String[] args) {
ForumService target = new ForumServiceImpl();
PerformanceHandler handler = new PerformanceHandler(target);

ForumService proxy = (ForumService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
handler
);

proxy.addTopic();
proxy.removeTopic();
}
}


(2)通过ProxyFactory简化AOP的实现

为了简化AOP实现过程,可以使用ProxyFactory类,ProxyFactory类是对JDK动态代理和CGLIB动态代理的一个封装,将定义好的目标被代理类和增强Adviceh注入到ProxyFactory中生成代理类实现AOP功能;

定义增强

public class UserBeforeAdvice implements MethodBeforeAdvice{
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("before the method");
}
}


在XML配置文件中将增强和目标代理类注入到ProxyFactoryBean中

<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 
<bean id="advice" class="aspectj.UserBeforeAdvice"></bean>

<bean id="target" class="aspectj.UserServiceImp"></bean>

<bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="aspectj.UserService"></property>
<property name="InterceptorNames" value="advice"></property>
<property name="target" value="target"></property>
</bean>

</beans>


(3)创建切点切面细化AOP操作

Spring通过切点定位到某些类的特定方法上,切点结合增强封装成切面用来具体实现AOP功能

定义切面类,在切面类中通过ClassFilter和MethodMatcher进行切点匹配;切面是对切点和增强的封装;

public class UserAdvisor extends StaticMethodMatcherPointcutAdvisor {
public boolean matches(Method method, Class<?> aClass) {
return "addUser".equals(method.getName());
}
}


在XML配置文件中将增强注入到切面中

<bean id="advice" class="aspectj.UserBeforeAdvice"></bean>

<bean id="advisor" class="aspectj.UserAdvisor">
<property name="advice" value="advice"></property>
</bean>


在XML配置文件中将切面和目标代理类注入到ProxyFactoryBean中

<bean id="advice" class="aspectj.UserBeforeAdvice"></bean>

<bean id="advisor" class="aspectj.UserAdvisor">
<property name="advice" value="advice"></property>
</bean>

<bean id="target" class="aspectj.UserService"></bean>

<bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="aspectj.Services"></property>
<property name="InterceptorNames" value="advisor"></property>
<property name="target" value="target"></property>
</bean>


(4) 通过自动创建代理简化AOP实现

使用ProxyFactoryBean实现AOP,每个需要被代理的Bean都需要使用一个ProxyFactoryBean进行配置;Spring提供了自动代理机制,底层使用BeanPostProcessor实现,在调动getBean()方法获取bean实例时会自动判断该类是否与切面匹配如果匹配则创建代理实例,否则创建普通实例;Spring的自动创建代理主要通过BeanNameAutoProxyCreator类,DefaultAdvisorAutoProxyCreator类,AnnocationAwareAspectjAutoProxyCreator类实现;

BeanNameAutoProxyCreator类:主要是为一组特定beanName的bean自动创建代理类,代理全部的方法;

DefaultAdvisorAutoProxyCreator类:扫描容器中的所有Advisor切面,自动将匹配的切面应用到Bean中;

AnnocationAwareAspectjAutoProxyCreator类:对AspectJ注解进行解析,扫描容器中的所有Advisor切面,自动将匹配的切面应用到Bean中;

定义切面类,在切面类中通过ClassFilter和MethodMatcher进行切点匹配;切面是对切点和增强的封装;

public class UserAdvisor extends StaticMethodMatcherPointcutAdvisor {
public boolean matches(Method method, Class<?> aClass) {
return "addUser".equals(method.getName());
}
}


在XML配置文件中将增强注入到切面中

<bean id="advice" class="aspectj.UserBeforeAdvice"></bean>

<bean id="advisor" class="aspectj.UserAdvisor">
<property name="advice" value="advice"></property>
</bean>


定义DefaultAdvisorAutoProxyCreator实例,自动扫描容器内的切面,并在调用getBean()是判断是否匹配,如果匹配则创建相应的代理类;

<bean id="advice" class="aspectj.UserBeforeAdvice"></bean>

<bean id="advisor" class="aspectj.UserAdvisor">
<property name="advice" value="advice"></property>
</bean>

<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>

<bean id="userService" class="aspectj.UserService"></bean>


(5) 通过AspectJ注解进一步简化AOP配置

利用@Aspect定义切面类,将增强和切点结合在切面类中

@Aspect

@Compent

public class UserAdvisor {
@Before("execution(* addUser(...))")
public void before(){
System.out.println("in the before");
}
}


定义AnnocationAwareAspectjAutoProxyCreator实例开启AspectJ注解模式,自动扫描容器内的切面,并在调用getBean()是判断是否匹配,如果匹配则创建相应的代理类;

<bean class="org.springframework.aop.framework.autoproxy.AnnocationAwareAspectjAutoProxyCreator"></bean>


如果使用了aop命名空间则使用aop标签定义

<aop:aspectj-autoproxy>


总结

Spring AOP主要是由sping-aop和sping-aspects组成;

AOP是一种面向切面编程的思想,是对面向对象的一种补充,在日志以及事务管理等方面有着较多的应用;

AOP实现的关键在于AOP框架能够为目标类创建AOP代理,AOP代理根据创建的形式分为静态代理和动态代理;静态代理是指子啊编译期生成代理类,动态代理是指在运行期间在内存中生成临时代理类;Spring AOP是动态代理,AspectJ是静态代理,虽然Spring引入Aspects包
a6d9
支持AspecJ注解等,但是底层代理实现仍然是通过动态代理;

Spring AOP实现

可以通过JDK动态代理或者CGLIB动态代理直接实现,以JDK动态代理为例,定义目标接口,被代理目标类和实现了AOP逻辑的实现了InnovocationHandler的处理类,调用Proxy类的newProxyInstance()方法生成代理类;

为了简化配置可以使用ProxyFactoryBean,将切点或切面,被代理目标类注入ProxyFactoryBean中生成代理类;

为了进一步简化配置,可以定义自动创建类autoProxyCreator,会在bean实例创建时,搜索容器内的切面,如果匹配则生成代理类实例,如果不匹配则生成普通实例;

为了进一步简化配置,使用AspectJ注解,在切面类上使用@Aspect注解,在容器初始化时会将该切面类加载到容器中,在bean实例创建时,搜索容器内的切面,如果匹配则生成代理类实例,如果不匹配则生成普通实例
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: