// ContainerImpl 中定义的静态内部类
/** * Injects a field or method in a given object. */ interface Injector extends Serializable { void inject(InternalContext context, Object o); } static class MissingDependencyException extends Exception { MissingDependencyException(String message) { super(message); } }
// 一些Injector 的实现类
static class FieldInjector implements Injector { final Field field; final InternalFactory<?> factory; final ExternalContext<?> externalContext; public FieldInjector(ContainerImpl container, Field field, String name) throws MissingDependencyException { this.field = field; field.setAccessible(true);// 此处貌似都是有必要的 //不使用构造函数是因为 Key类中构造函数定义为private Key<?> key = Key.newInstance(field.getType(), name); factory = container.getFactory(key);//注意传入ContainerImpl呀! if (factory == null) { throw new MissingDependencyException( "No mapping found for dependency " + key + " in " + field + "."); } //不使用构造函数不知道为何了????? this.externalContext = ExternalContext.newInstance(field, key, container); } // 此处是核心关键调用的方法 public void inject(InternalContext context, Object o) { ExternalContext<?> previous = context.getExternalContext(); context.setExternalContext(externalContext); try { // 将指定对象变量上(o)此 Field 对象表示的字段设置为指定的新值(param2)。 field.set(o, factory.create(context)); } catch (IllegalAccessException e) { throw new AssertionError(e); } finally { // 此处谁能告诉我是干什么的? context.setExternalContext(previous); } } }
//
static class ParameterInjector<T> { final ExternalContext<T> externalContext; final InternalFactory<? extends T> factory; public ParameterInjector(ExternalContext<T> externalContext, InternalFactory<? extends T> factory) { this.externalContext = externalContext; this.factory = factory; } //member 反映有关单个成员(字段或方法)或构造方法的标识信息。 T inject(Member member, InternalContext context) { ExternalContext<?> previous = context.getExternalContext(); context.setExternalContext(externalContext); try { return factory.create(context); } finally { // 此处又来了 context.setExternalContext(previous); } } }
static class ConstructorInjector<T> { final Class<T> implementation; final List<Injector> injectors; final Constructor<T> constructor; final ParameterInjector<?>[] parameterInjectors; ConstructorInjector(ContainerImpl container, Class<T> implementation) { this.implementation = implementation; //内部类提供的内部方法 constructor = findConstructorIn(implementation); constructor.setAccessible(true); //也来了 try { Inject inject = constructor.getAnnotation(Inject.class); parameterInjectors = inject == null ? null // default constructor. : container.getParametersInjectors( constructor, constructor.getParameterAnnotations(), constructor.getParameterTypes(), inject.value() ); } catch (MissingDependencyException e) { throw new DependencyException(e); } injectors = container.injectors.get(implementation); } //内部类中提供的方法 @SuppressWarnings("unchecked") private Constructor<T> findConstructorIn(Class<T> implementation) { Constructor<T> found = null; Constructor<T>[] declaredConstructors = (Constructor<T>[]) implementation.getDeclaredConstructors(); for(Constructor<T> constructor : declaredConstructors) { if (constructor.getAnnotation(Inject.class) != null) { if (found != null) { throw new DependencyException("More than one constructor annotated" + " with @Inject found in " + implementation + "."); } found = constructor; } } if (found != null) { return found; } // If no annotated constructor is found, look for a no-arg constructor // instead. try { return implementation.getDeclaredConstructor(); } catch (NoSuchMethodException e) { throw new DependencyException("Could not find a suitable constructor" + " in " + implementation.getName() + "."); } } /** * Construct an instance. Returns {@code Object} instead of {@code T} * because it may return a proxy. */ Object construct(InternalContext context, Class<? super T> expectedType) { ConstructionContext<T> constructionContext = context.getConstructionContext(this); // We have a circular reference between constructors. Return a proxy. if (constructionContext.isConstructing()) { // TODO (crazybob): if we can't proxy this object, can we proxy the // other object? return constructionContext.createProxy(expectedType); } // If we're re-entering this factory while injecting fields or methods, // return the same instance. This prevents infinite loops. T t = constructionContext.getCurrentReference(); if (t != null) { return t; } try { // First time through... constructionContext.startConstruction(); try { Object[] parameters = getParameters(constructor, context, parameterInjectors); t = constructor.newInstance(parameters); constructionContext.setProxyDelegates(t); } finally { constructionContext.finishConstruction(); } // Store reference. If an injector re-enters this factory, they'll // get the same reference. constructionContext.setCurrentReference(t); // Inject fields and methods. for (Injector injector : injectors) { injector.inject(context, t); } return t; } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } finally { constructionContext.removeCurrentReference(); } } }
// Container接口实现类中需要 重要的变量定义和方法定义
ThreadLocal<Object[]> localContext = new ThreadLocal<Object[]>() { protected InternalContext[] initialValue() { return new InternalContext[1]; } }; /** * Looks up thread local context. Creates (and removes) a new context if * necessary. */ <T> T callInContext(ContextualCallable<T> callable) { InternalContext[] reference = (InternalContext[]) localContext.get(); if (reference[0] == null) { reference[0] = new InternalContext(this); try { return callable.call(reference[0]); } finally { // Only remove the context if this call created it. reference[0] = null; } } else { // Someone else will clean up this context. return callable.call(reference[0]); } } // 注意此处的接口定义 interface ContextualCallable<T> { T call(InternalContext context); }
相关推荐
例如,通过Struts2-Spring-plugin,可以实现Action的依赖注入,增强应用的可测试性和可维护性。 总的来说,张龙圣思园的Struts2学习笔记是全面了解和掌握Struts2框架的宝贵资源,无论你是初学者还是有经验的开发者...
这个插件的主要目的是简化在基于Struts2的应用程序中整合Spring的功能,如依赖注入(DI)、AOP(面向切面编程)以及事务管理等。下面我们将深入探讨Struts2、Spring框架以及它们之间的集成。 **Struts2框架** ...
Struts2可以很好地与Spring框架集成,实现依赖注入(DI)和AOP(面向切面编程),提高代码的可测试性和可维护性。 以上就是Struts2基本类库中涉及的关键知识点。学习和理解这些内容,可以帮助开发者有效地利用...
1. **Spring集成**:Struts2可以无缝集成Spring,使得Action可以直接从Spring容器获取依赖,实现依赖注入,有利于解耦和测试。 2. **Hibernate集成**:Struts2提供了Hibernate插件,简化了数据访问层的操作,可以...
9. **Action类和结果**:Action类是业务逻辑的载体,它可以是简单的Java类,通过注解或者XML配置与Struts2关联。结果定义了Action执行后跳转的目标,可以是JSP、Freemarker模板或其他结果类型。 10. **Interceptor...
最后,Struts2与Spring框架的集成也是常见的应用场景,可以实现依赖注入,方便管理Action的生命周期。如果这个入门程序包含Spring的集成,那么你还会了解到如何配置Spring和Struts2之间的协作。 总的来说,"Struts2...
它在原有的Struts1基础上进行了很多改进,引入了更多现代化的开发理念和技术,如依赖注入(DI)、面向切面编程(AOP)以及插件架构等。这个"Struts2小demo"是一个基础的学习资源,旨在帮助开发者开启SSH(Spring、...
8. **Action的属性注入与调用**:在Struts2中,Action的属性可以通过配置文件进行注入,而Action的调用则依赖于配置的拦截器。拦截器会负责调用Action的execute方法,以及处理请求参数的设置和返回结果的解析。 9. ...
Spring以其强大的依赖注入(DI)和面向切面编程(AOP)能力,而Struts2则以其优秀的MVC设计模式著称,两者结合可以构建出高效、可维护的Web应用。本文将基于"spring+struts2整合源码"的标题和描述,详细讲解Spring和...
结合Spring框架,可以实现依赖注入,提高代码的可测试性和可维护性。 五、学习资源 本教材《Struts2》将深入讲解上述概念,并通过实例演示如何创建一个简单的Struts2应用,包括Action的编写、配置文件的设置、拦截...
Struts2与Spring集成,可以实现Action类的依赖注入,提高代码的可测试性和可维护性。 **Maven** Maven是一个项目管理和综合工具,主要用于构建、文档生成、报告、依赖管理和项目信息管理。通过POM(Project Object ...
关于依赖注入,Struts2可以与Spring框架结合使用,通过Spring管理Action的依赖,实现更高级别的控制反转和依赖注入。这增强了代码的可测试性和模块化。 在安全性方面,Struts2提供了一套安全相关的拦截器,如...
Struts2的核心是Action类,每个Action对应一个特定的用户操作,通过配置Struts2的配置文件(通常为struts.xml),我们可以定义这些操作的映射路径,以及它们与视图之间的关联。 Spring3则是一个全面的企业级应用...
- **struts2-spring-plugin.jar**(如果使用Spring):整合Spring框架,提供依赖注入功能。 - **struts2-struts1-plugin.jar**(如果需要与Struts1兼容):提供与Struts1的兼容性。 5. **模板引擎**:在"struts2...
Struts2可以方便地与Spring、Hibernate等其他框架集成,实现依赖注入、持久化等功能,构建完整的MVC应用。 **9. 异常处理** Struts2提供了一套完善的异常处理机制,允许开发者自定义错误页面和错误处理策略,确保...
**Spring** 是一个全面的Java企业级应用框架,它的核心特性包括依赖注入(DI)和面向切面编程(AOP)。在本项目中,Spring主要负责管理Bean,如数据库连接池、事务管理、DAO和Service等。通过Spring的AOP,我们可以...
Struts2和Hibernate是两种非常重要的Java开源框架,它们分别在Web应用的MVC(Model-View-Controller)架构和...在实际项目中,我们还可以进一步优化,比如引入Spring框架进行依赖注入,提高代码的可维护性和灵活性。
通过这种方式,Struts2负责接收请求并调用Spring管理的业务逻辑组件,Spring则负责依赖注入和事务管理,iBatis则在后台默默地处理数据库交互。这样的架构使得代码更加模块化,降低了耦合度,便于维护和扩展。 总的...
在整合Spring时,我们通常会利用Spring的Action代理来替代Struts2默认的Action实例化方式,这样可以将Action的创建和依赖注入交给Spring容器来管理。具体实现包括在Struts配置文件中声明Spring插件,并在Spring的...
ObjectFactory遵循依赖注入(Dependency Injection)原则,确保了对象的生命周期管理和依赖关系的自动装配,使得框架更加轻量级且易于扩展。 ### 三、总结 Struts2框架通过精巧的设计和组件化的实现,提供了高效、...