分类: Java
2013-04-07 22:52:40
1,spring是一个开源的控制反转(IOC:Inversion of Control)和面向切面(AOP)的容器框架
控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的。这样控制权有应用转移到了外部容器,控制权的转移就是所谓反转
依赖注入(Dependency Injection):在运行期,由外部容器动态地将依赖对象注入到组件中
spring的优点:
(a)降低组件之间的耦合度,实现软件各层之间的解耦合。
(b)可以使用容器提供的众多服务:事务管理服务,消息服务等等。
(c)容器提供单例模式的支持,开发人员不需要自己写代码。
(d)容器提供了AOP技术,利用它很容易实现权限的拦截,运行期间监控等功能。
(e)提供了很多的辅助类,JdbcTempelet
(f)支持主流框架
轻量级:根据打开的服务多少来判断,spring默认打开核心服务是轻量级的,如果spring打开了所有服务就变成重量级的了,EJB默认打开所有的服务是重量级的
2,spring实现的基本原理:
(1)用dom4j解析配置文件(在构造函数中):将配置文件中的bean解析成一个对象(里面含有id和class,list集合(集合中放property,里面含有属性name,ref,value)),遍历节点,创建bean对象,把id和clazz放进对象,在遍历property,把property放在集合中,然后把所有bean对象放在list集合中
(2)创建bean对象:解析完之后实例化对象,遍历bean集合,将id作为键,使用class的字符串和反射机制创建对象实例,都放在map中
(3)注入对象:遍历bean集合list,根据id查找map得到bean对象,根据bean得到property集合,在遍历property集合,如果是含有ref,注入对象,如果是含有value使用commons-beanutils的jar包自动将字符串转为基本数据类型
在写一个getBean方法得到对象的,使用的时候,使用传id得到对象
3,spring的IOC开发
(1)添加jar包
俩个必须的包:(dist)spring.jar,(lib\jakarta-commons)commons-logging.jar
使用aop的时候:(lib\aspectj)aspectjrt.jar,aspectjweaver.jar
使用连接池的时候:(lib\jakarta-commons) commons-pool.jar, commons-dbcp.jar
(log4j) log4j-1.2.15.jar
使用注解时:lib/j2ee/common-annotations.jar
(2)注入的方式
使用构造器注入:
使用setter注入
自动装配注入:不建议使用,自动装配可能出现问题,因为有的不想装配进去,结果都装配进去了。
使用注解注入
(3)bean的作用域:单例和原型
Bean的生命周期:先进行实例化,在进行初始化,最后是销毁
bean的实例化和销毁:
实例化:默认是单例,在容器实例化时(解析beans.xml文件)就进行实例化对象
当作用域是原型,在调用getBean方法的时候才进行实例化
当是单例时,如果想要延迟对象的初始化使用属性lazy-init="true"
实例化中的的初始化和销毁方法:
初始化方法在原型中,每次创建一个对象都会调用init方法,但destroy方法在原型中是不调用的,一般init和destroy不和原型一起用
实例化bean的三种方式:
最常用的一种
静态工厂
实例工厂
(4)注入集合:Set,List,properties,Map
测试的时候:
实例化spring容器,最好的方式是采用相对路径:
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"beans.xml"});
ApplicationContext ctx = new ClassPathXmlApplicationContext(“XML的名称”);
得到Bean对象PersonService service = (PersonService)ctx.getBean("personService(Bean中的id的值)“);
(5)BeanFactory是IOC的最顶层的接口,在第一次getBean时才会进行创建对象,在启动beanFactory的时候必须含有一种日志框架,否则启动报错,我们使用Log4j
BeanFactory和ApplicationContext另一个最大的区别是:后者会利用java反射机制自动识别出配置文件中定义的BeanPostProcessor等三个接口,而前者需要在代码中通过手工调用addBeanPostProcessor()方法进行注册
4,springAOP
(1)AOP术语:
(a)连接点:对哪个方法进行拦截,这些方法就是连接点(拦截到的点)
(b)通知(增强):织入到目标连接点上的一段程序代码
在方法前调用的通知:前置通知
放在方法执行后:后置通知
出现异常执行的是:例外通知
无论是否异常都执行的:最终通知
(c)目标对象:增强逻辑的织入目标类
(d)织入:将切面应用到目标对象并导致代理对象创建的过程叫织入
(e)引入(Introduction)在不修改代码的前提下,引入可以再运行期动态的强组成
(g)切入点:对那些连接点进行拦截的定义
(2)(a)使用JDK动态代理时,必须让被代理类实现接口,面向接口编程
代理实现InvocationHandler接口
public Object createProxy(Object target){
this.target=target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("开启事务...");
Object value = method.invoke(target, args);//回调被代理对象中的方法
System.out.println("提交事务...");
return value;
}
(b)Cglib实现的动态代理,被代理类不用实现接口
代理实现MethodInterceptor接口
cglib创建的代理实际上是继承了目标类,对目标类中所有的非final方法进行覆盖
public Object createProxy(Object target){
this.target=target;
Enhancer enhancer = new Enhancer();
//设置被代理类
enhancer.setSuperclass(target.getClass());
//设置回调函数
enhancer.setCallback(this);//当调用被代理目标中方法,intercept会被自动调用
return enhancer.create();//通过字节码产生代理对象
}
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
System.out.println("开启事务...");
Object value = method.invoke(target, args);//回调被代理目标中的方法
System.out.println("提交事务....");
return value;
}
AOP应用: