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

今天先写这么多了~  第一次发博客,希望有什么地方写错大家帮忙指正!

 

posted @ 2013-12-10 20:56  young kind  阅读(531)  评论(0)    收藏  举报