Spring点点滴滴---spring框架的架构
最近看了一篇很不错的文章 http://developer.51cto.com/art/201006/205212.htm
现在记一下心得体会。这篇文章让我这菜鸟学到很多东西。
面试时经常被问起Spring是什么,这是个很泛的问题,不同人答案不大一样。取决于个人对于这个框架的了解程度。这个问题其实可以从spring框架的架构方面去回答。Spring是由core,context,beans几大核心组件构成基本架构,并由在此基本架构上实现的上层功能(如AOP,Web,Transaction)构成的框架。
在3个基本组件中Bean组件可以说最关键的,因为Spring设计理念就是面向Bean的编程。Spring该理念让我们的编程变得更简单舒服,我们对象的依赖关系可以通过使用配置文件来管理,这就是它的依赖注入机制。对象的这种关系存放于Ioc容器中管理。这里注入的意思就是:一个对象通过spring配置引入另一个对象。
在这里又发现一个问题:我们在代码里面不是已经把另一个对象的包给导入了吗?比如TestService 内想使用 TestDao这个类,那在TestService内就已经先导入这个类呀。但是实际情况是,如果不在Spring里配置,把TestDao注入TestService 则程序执行不了。为什么呢?(以下是我的分析,不一定正确,如果错了请务必帮忙指正,谢谢):因为我们的TestDao类已经交给了Spring托管,项目部署的时候就会自动创建该类的一个备份,在Spring中配置注入就会自动在TestService中初始化这个TestDao。只是在代码中导入TestDao是不够的,因为Dao层涉及到对数据库的操作,需要用到Spring中的Transaction来管理。
再介绍下其他两个基本组件Core,Context。Context读取我们的配置文件,并解析各个Bean中的关系,生成Bean的实体并存放在Ioc容器中。ApplicationContext是Context的顶级父类。在代码中可通过这个父类来获取Bean。
如:
public ApplicationContext context = new FileSystemXmlApplicationContext("WebRoot/WEB-INF/applicationContext.xml"); public FollowService service = (FollowService)context.getBean("FollowService");
可用来测试代码。
总的来说ApplicationContext有几个任务:1.标识一个应用 2.利用BeanFactory创建一个对象 3.保存对象关系表 4.捕获各种事件
Ioc容器的拓展点:
BeanFactoryPostProcessor,BeanPostProcessor分别是在构建BeanFactory和构建Bean对象时调用。还有就是InitializingBean和DisposableBean 他们分别是在Bean实例创建和销毁时被调用。我们可以实现这些接口的方法,在构建与销毁Bean的时候加入自己的功能。另外一个拓展点是FactoryBean,这个可以让用户通过实现该工厂接口定制实例化Bean。
以下是FactoryBean的应用:
import org.springframework.beans.factory.FactoryBean; public class CarFactoryBean implements FactoryBean{ private String carInfo; public String getCarInfo() { return carInfo; } public void setCarInfo(String carInfo) { this.carInfo = carInfo; } public Object getObject() throws Exception { System.out.println("返回由FactoryBean创建的Bean实例"); Car car = new Car(); String[] infos = carInfo.split(","); car.setBrand(infos[0]); car.setMaxSpeed(Integer.parseInt(infos[1])); car.setColor(infos[2]); return car; } public Class getObjectType() { return Car.class; } public boolean isSingleton() { return true; } }
beans.xml
<bean id="car" class="com.Spring.FactoryBean.CarFactoryBean">
<property name="carInfo" value="宝马,200,black"/>
</bean>
CreateBean.java
public class CreateBean { public static void main(String[] args) { ApplicationContext cxt = new ClassPathXmlApplicationContext( "com/Spring/FactoryBean/beans.xml"); Car car = (Car)cxt.getBean("car"); car.introduce(); } }
接下来讨论下Spring的AOP。AOP是基于刚才讲到的IOC容器来工作的。了解AOP实现之后,我对IOC容器的使用有更深的理解。
附上一篇讲AOP的文章 http://pandonix.iteye.com/blog/336873 讲的挺简明易懂。
首先,得了解Spring的动态代理,具体的配置在上文贴出来的文章中都讲到了。我主要说说我的理解吧。。
使用AOP中的JDK动态代理是利用代理模式来实现的。Spring AOP实际上是实现Spring的拓展点来完成这个特性,可以在我们执行代理对象里面某个method前后自动执行我们规定的代码,而不影响method的其他方法执行,降低程序耦合。常用的地方就是我们项目的日志管理,可以用aop把我们写的日志管理模块与数据库操作相挂钩,在数据库操作的时候自动记录数据库日志。
AOP与动态代理究竟是什么关系呢?这个要先讲讲动态代理的知识:
总的来说就是,代理类可以代理任何对象,动态代理类的字节码在java程序运行时由Java反射机制动态生成。这么说还比较抽象,看个例子就明白了。
代理类接口:
public interface InvocationHandler { public Object invoke(Object proxy,Method method,Object[] args); }
Service类
package org.iti.wxl.dynamicproxy; public interface UserService { public void addUser(); public void deleteUSer(); }
ServiceImpl
package org.iti.wxl.dynamicproxy; public class UserServiceImpl implements UserService { @Override public void addUser() { System.out.println("==add user=="); } @Override public void deleteUSer() { System.out.println("==delete user=="); } }
代理类
package org.iti.wxl.dynamicproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class UserServiceImplProxy implements InvocationHandler { private Object target; public Object bind(Object target){ this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; System.out.println("user add begin!"); result = method.invoke(target, args); System.out.println("user add end!"); return result; } }
测试类
package org.iti.wxl.dynamicproxy; public class DynamicProxy { public static void main(String[] args) { UserServiceImplProxy proxy = new UserServiceImplProxy(); UserService userServiceProxy = (UserService)proxy. bind(new UserServiceImpl()); userServiceProxy.addUser(); System.out.println("========"); userServiceProxy.deleteUSer(); } }
测试结果:
user add begin!
==add user==
user add end!
========
user add begin!
==delete user==
user add end!
代理模式就是如果要调用类A,则建立一个类B实现与A一样的接口,然后调用B。这样做的好处就是像上面的代码一样,可在调用A之前与之后调用我们自定义的代码。
在AOP中,如果要代理一个类,比如之前写到的UserService,我们只需写一个代理类,并且在applicationContext.xml中配置,为UserService指定代理类。代码如下:
代理类代码:
package org.iti.wxl.springaop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class MyInterceptor { @Pointcut("execution(* org.iti.wxl.springaop..*.*(..))") private void pointCutmethod(){ } @Before("pointCutmethod() && args(userId)") public void doBefore(String userId){ System.out.println("前置通知 " + userId); } @AfterReturning("pointCutmethod()") public void doAfterReturning(){ System.out.println("后置通知"); } @AfterThrowing("pointCutmethod()") public void doAfterException(){ System.out.println("异常通知"); } @After("pointCutmethod()") public void doAfter(){ System.out.println("最终通知"); } @Around("pointCutmethod()") public Object doAround(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("环绕开始"); Object object = pjp.proceed(); System.out.println("环绕结束"); return object; } }
spring中的配置
<?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: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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <!-- 使用 annotation --> <context:annotation-config /> <!-- 启用aop --> <aop:aspectj-autoproxy proxy-target-class="true" /> <bean id="myInterceptor" class="org.iti.wxl.springaop.MyInterceptor"/> <bean id="userService" class="org.iti.wxl.springaop.UserServiceImpl"/> </beans>
代码参考自:http://www.iteye.com/topic/1127544
今天先写这么多了~ 第一次发博客,希望有什么地方写错大家帮忙指正!

浙公网安备 33010602011771号