`
chineseoa
  • 浏览: 102912 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

自行编写ProxyFactoryBean,感受Spring AOP的核心

阅读更多
Spring中AOP编程的本质是:无须修改源码增加系统功能。所谓的系统功能即为AOP中的A,方面,体现在代码上称为Advice(增强):即日志、审核、权限、计时等每个系统均可能要使用到的功能。在感受AOP让我们见证神奇的背后,我们可以通过以下方式不同程度地实现:

1.  JavaSE 动态代理;
    从JDK1.3开始,便加入了可协助动态生成代理类的API。在这些API中,一个主要接口是
       java.lang.reflect.InvocationHandler以及import java.lang.reflect.Proxy。在动态代理中,我们主要编写该接口的实现类型。

2.  动态字节码生成;
     针对指定的类动态生成一个子类,并且覆盖其中的方法,从而增加系统功能。其中最流行的工具是:
     CGLIB(Code Generation Library).
     缺点:无法为 final 方法或类 提供代码。

3.   Java代码生成;
     生成新的Java源码,在其中提供横切性的代码,例如EJB的代码生成策略;
     由于动态代理和动态字节码生成技术的出现,这种做法正在逐渐退出使用;

4.  使用定制的类加载器;
     自定义类加载器,在一个类被加载时自动对其进行横切入系统功能,改变new操作符的行为。
     JBoss和AspectWerkz采用这种做法。
     缺点:偏离Java标准,在某些应用服务器中可能出现问题,因为J2EE服务器需要控制整个类加载的层级体系。

5.  语言扩展;
     增加Java语言功能,使其在OOP编程基础上从语言级别上支持AOP。这一点类似于C++扩展C,引入OO概念一样。
     AspectJ就对Java进行了扩展。
     缺点:复杂,且引用新的语言。

     OOP编程中一些模式也已经解决了AOP希望解决的部分问题:
     . Decorator(装饰器模式): 类似于静态代理;
     . CORBA在处理远程调用时提供了拦截器的概念;
     . Servlet2.3规范引入的servlet拦截器会在处理Web请求的前后被调用;

     这些解决方案的主要问题是:它们将拦截器的代码与特定的API或上下文环境(例如:处理远程调用)绑在一起,不够通用。

Spring中AOP构建在动态代码和字节码生成概念基础上, 提供更优雅、更通用的解决方案。Spring中将要增加的系统功能体现为Advice接口的实现类型。根据系统功能加入目标对象的时刻又分为:

1. 前增强(before,pre):在连接点调用之前,首先调用增强;
2. 后增强(after,post):在连接点调用之后,首先调用增强;
      a. 返回后增强(after returning advice):在调用成功(没抛异常)之后;
      b. 抛出增强(throws advice):在抛出某种特定类型的异常之后;
      c. 后增强(after advice):在连接点调用后,不管是否抛异常;
3. 环绕增强(around):完全控制流程,除完成本身工作,还要负责主动调用连接点;
      不同增强授受的参数不同;例如后增强获得实际方法的返回值,但抛出增强则不能;

我们应从可用性角度出发,尽量使用功能最弱,目的最明确的增强,这样可以使程序更加清晰。

Spring中为了对系统功能加入到目标对象的方法进行进一步精细控制,提供PointCut接口。然后将系统功能结合到目标对象的工作交由配置文件完成。Advice编写是简单的,PointCut接口的实现类是现成的,配置的代码是可以参考的,但配置文件中一个名为ProxyFactoryBean的工作原理是很重要的。为了能近距离感受AOP神奇背后的普通,我们可以自行编写ProxyFactoryBean。在看具体的源码之前,对ProxyFactory所实现的接口稍做说明:

1. BeanFactoryAware: 实现该接口的Bean对象在由Spring框架实例化完后,会由Spring框架自动注入BeanFactory对象;
2. FactoryBean: 实现该接口,通过该Bean对象所配置的Bean的名称获得的不是该Bean对象,而是该Bean对象方法getObject()返回的对象;
3. InvocationHandler: 实现该接口,动态地改变所执行原方法的功能,实现在原方法前、后或前后加入增强;

原码如下:

package common;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.FactoryBean;

public class MyProxyFactoryBean implements 
	BeanFactoryAware, FactoryBean, InvocationHandler{
	private Object target;
	private Class[] proxyInterfaces;
	private List interceptorNames=new ArrayList();
	private List realInterceptorNames=null;
	private BeanFactory factory;
	
	@Override
	public Object getObject() throws Exception {
		return Proxy.newProxyInstance(
			target.getClass().getClassLoader(),
			proxyInterfaces,
			this
		);
	}

	@Override
	public Class getObjectType() {
		return target.getClass();
	}

	@Override
	public boolean isSingleton() {
		return true;
	}

	public void setTarget(Object target) {
		this.target=target; 
	}
	
	public void setProxyInterfaces(String proxyInterfaces) {
		try {
			this.proxyInterfaces=new Class[]{Class.forName(proxyInterfaces)};
		} catch (ClassNotFoundException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public Object invoke(Object proxy, 
			Method method, Object[] args)
			throws Throwable {
		if(realInterceptorNames==null) {
			realInterceptorNames=new ArrayList();
			for(Object o: interceptorNames) {
				realInterceptorNames.add(factory.getBean(o.toString()));
			}
		}
		for(Object o: realInterceptorNames) {
			if(o instanceof MethodBeforeAdvice)
				((MethodBeforeAdvice)o).before(method, args, target);
		}
		Object result=method.invoke(target,args);
		
		return result;
	}
	
	public void setInterceptorNames(
			List interceptorNames) {
		this.interceptorNames=interceptorNames;
	}

	@Override
	public void setBeanFactory(BeanFactory arg0) throws BeansException {
		this.factory=arg0;	
	}
}

0
0
分享到:
评论

相关推荐

    spring aop用到jar包.rar

    总的来说,这个压缩文件"spring aop用到jar包.rar"包含了实现Spring AOP所需的一系列核心库,它们共同构成了Spring AOP的基础架构,使得我们可以方便地编写和应用切面,提高代码的可维护性和可扩展性。在实际项目中...

    spring aop 学习笔记

    - `org.springframework.aop.framework.ProxyFactoryBean` 和 `org.springframework.aop.framework.JdkDynamicAopProxy` 是动态代理的关键类。 - `org.springframework.aop.aspectj.AspectJExpressionPointcut` ...

    Spring AOP的底层实现技术

    深入研究Spring AOP的源码,可以帮助我们更好地理解其工作原理,例如,可以查看`org.springframework.aop.framework.ProxyFactoryBean`、`org.springframework.aop.aspectj.autoproxy.AspectJProxyFactoryBean`、`...

    Spring之AOP介绍

    Spring AOP提供了一种优雅的方式,使开发者能够更加专注于业务逻辑的编写,同时确保诸如事务管理、日志记录等功能的统一管理和实现。通过上面的介绍和示例,我们可以看到Spring AOP的强大之处,以及它是如何简化开发...

    Spring AOP之增强

    在阅读源码时,我们可以深入了解Spring AOP的代理实现,例如`Advised`接口和`AopProxy`接口,以及`DefaultAdvisorAdapterRegistry`、`ProxyFactoryBean`等类的作用。理解这些内部机制有助于我们更好地利用Spring AOP...

    spring aop

    压缩包中的文件 "spring aop源代码分析.doc" 可能包含了对Spring AOP源代码的详细解读,分析了其关键类和方法,比如`org.springframework.aop.framework.ProxyFactoryBean`、`org.springframework.aop.aspectj....

    spring基于AOP实现事务

    <bean id="transactionalService" class="org.springframework.aop.framework.ProxyFactoryBean"> *">PROPAGATION_REQUIRED, -java.lang.Exception ``` 这里,`realService`是我们的业务服务对象,`...

    Spring AOP介绍及源码分析

    **Spring AOP介绍** ...学习并掌握Spring AOP及其源码分析对于提升作为IT专业人员的技术水平至关重要,它不仅能够帮助我们编写更加优雅和简洁的代码,还能使我们更好地应对复杂的企业级应用需求。

    《Java EE企业开发框架》 Spring AOP实验报告

    3. **学习并实践基于代理的AOP实现**:通过本实验,学生将了解如何利用Spring提供的代理机制(如JDK动态代理、CGLIB代理、ProxyFactoryBean等)来实现AOP功能。 #### 三、实验设计与实现 ##### 1. 定义`MyClass`类...

    Spring AOP总结

    Spring AOP的实现主要涉及到`org.springframework.aop.framework.ProxyFactoryBean`、`org.springframework.aop.framework.DefaultAopProxyFactory`、`org.springframework.aop.aspectj.AspectJExpressionPointcut`...

    spring2-aop入门实例教程

    - **ProxyFactoryBean**:Spring AOP中的代理工厂Bean,用于创建代理对象。 #### 六、实战示例:模拟Warcraft游戏 - **示例简介**:通过一个模拟游戏的例子来演示如何使用Spring AOP来处理游戏中的横切关注点。 - *...

    spring_AOP实现方法大全

    在Spring框架中,面向切面编程(Aspect-Oriented Programming,简称AOP)是一种强大的工具,它允许开发者定义“横切关注点”,这些关注点通常涉及日志、事务管理、安全性等,可以独立于业务逻辑进行编写。Spring AOP...

    spring入门学习-6、AOP几种配置方式详解.pdf

    这种方式允许开发者在 Spring 的配置文件中直接声明 AOP 的切面、切入点以及通知等元素,而无需编写复杂的 Java 代码。 - **切面声明**:使用 `<aop:aspect>` 元素来定义一个切面。 - **切入点声明**:使用 `<aop:...

    spring源代码分析:aop的实现

    在Spring中,AOP的核心类包括:AspectJExpressionPointcut、AdvisedSupport、ProxyFactoryBean等。AspectJExpressionPointcut负责解析并匹配切点表达式,AdvisedSupport则管理着通知、目标类、代理类型等信息,而...

    spring电子讲义

    - **Spring AOP**:作为Spring框架的核心组件之一,Spring AOP使用纯Java实现,并遵循AOP联盟定义的标准接口。 2. **Spring AOP的特点**: - **非强制依赖**:Spring IoC容器(包括BeanFactory和...

    spring-framework-5.0.2.RELEASE-中文注释版-终极完美版.rar

    在AOP部分,`org.springframework.aop.framework.ProxyFactoryBean`用于创建代理对象,实现切面功能。 Spring框架还支持注解驱动开发,如`@Autowired`用于自动装配依赖,`@Service`、`@Repository`和`@Controller`...

    spring 源码中文注释

    Spring框架是Java开发中最广泛应用的轻量级框架之一,它以IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)为核心,极大地简化了企业级应用的开发工作。这份"spring 源码...

    spring源码spring-framework-4.3.2.RELEASE

    `org.springframework.aop`包下包含了AOP的核心实现,如`Advised`接口和`ProxyFactoryBean`类。 二、数据访问支持 1. **JDBC抽象层**:Spring提供了对JDBC的简化封装,通过`JdbcTemplate`和`SimpleJdbcTemplate`,...

Global site tag (gtag.js) - Google Analytics