Spring

一。Spring简介

1.Spring是一个轻量级的javaEE解决方案,是众多优秀设计模式的整合
  Spring 框架中使用了了工厂(factory) 代理(proxy) 模板(template)三种模式
我们可以认为Spring的核心就是工厂

2.工厂设计模式
作用:工厂设计模式的主要作用就是生产对象(创建对象)
好处:解耦和
耦合:代码之间的强关联性体现在  代码的修改,相互影响
工厂设计模式的应用:建立一个工厂类,由工厂来负责对象的创建 在工厂中利用反射获取类的对象
注意:工厂全部都是重量级资源:占内存多  功能强 一个应用只需创建一个工厂并确保线程安全

3.Spring工厂的开发步骤
① 创建类

② 配置Spring的配置文件applicationContext.xml中写 

        <bean id="userDAO" class="userDAO的权限定名"></bean>
        ③ 使用步骤(在java类中)
        //创建工厂
	ApplicationConText ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
	//获得对象
	Account acc = (Account)ctx.getBean("userDAO");
4.Spring工厂创建对象的原理
① 通过读取sqring的配置文件 获取权限定名  在通过反射调用无参构造方法创建类的对象
② FactoryBean
作用:在spring工厂中用于创建复杂的对象
【1】简单对象
可以直接通过构造方法创建的对象
【2】复杂对象(接口类型)
不能通过 new 运算符直接创建对象

[1]FactoryBean的开发步骤:实现FactoryBean接口  实现内部规定的方法

               public Object getObject(){
	            ///作用:用于书写创建赋值对象的代码,并把创建的赋值对象作为方法的返回值
		}
		public Class getObjectType(){
		    ///返回创建的复杂对象的Class对象
		}
		public boolean isSingleton(){
		    //控制复杂对象的创建次数
		    //返回true意味着Spring工厂只会创建一个复杂对象
		    //返回false意味着每一次调用Spring工厂都会创建一个新的复杂对象
		    //根据所要创建的对象特性来确定返回true或false
		}

                【3】在FactoryBean应用过程中,可以通过 &id 的形式获得Class类型的对象

              例:
		ApplicationContext ctx = new ClassPathXmlApplicationContext("/application.properties");	
		ConnectionFactoryBean cfb = (ConnectionFactoryBean)ctx.getBean("&conn");
    ③ 控制简单对象的创建次数
    
       例:<bean id="xx" class="xx" scope="xx">
	  当scope="singleton"  那么这个简单对象只会被创建一次
	  当scope="prototype"  那么这个简单对象每一次都会创建一个新的对象
	  默认值为:singleton
        【1】Spring为什么会控制对象的创建次数
        [1]对象创建会拖延程序的运行效率
        [2]对象创建过多会占用过多的有限内存资源
    所以Spring控制对象的创建次数可以提高程序的运行效率,减少内存的不必要浪费
【2】哪些对象需要创建多次  哪些对象只需要创建一次
[1]只创建一次的对象
例:SqlSessionFactory  XXXDAO  XXXService
[2]需要创建多次的对象
Connection   ShopingCart   Action(struts2的)

在bean标签中添加一个scope属性

    ④ 工厂创建对象的生命周期(单例类型的对象)
【1】对象什么时候被工厂创建
工厂创建时,对象被创建
【2】对象什么时候被工厂销毁
工厂被关闭的时候,对象被销毁
【3】生命周期方法
[1]对象中任意定义一个初始化方法,Spring会在这个对象创建之后,自动调用初始化方法中的功能
         在实体类中定义一个方法后  在配置文件中的bean标签中 添加一个属性 init-method="方法名"
    这样Spring会在对象被创建后立即执行这个方法
[2]对象中任意定义一个销毁方法,Spring会在这个对象销毁之前,自动调用销毁方法中的功能
    在实体类中定义一个方法后  在配置文件中的bean标签中 添加一个属性 destroy-method="方法名"
    这样Spring会在对象被销毁之前调用这个方法
    ⑤ 配置信息参数化
作用:把Spring配置文件中,哪些需要经常修改的字符串,从Spring配置文件中转移到小的配置文件中
好处:利于后续的维护
【1】开发步骤
[1]准备小配置文件 :jdbc.properties

[2]小配置文件与Spring的配置文件整合

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-3.2.xsd"
>
导入context包指定小配置文件路径
<context:property-placeholder location="classpath:/jdbc.properties"/>
                        在Connection的value标签中用展位符${driver}这种形式通过键获取小配置文件中的值
        注意:Spring的小配置文件中的用户名不能使用username 
        【2】自定义类型转换器(SpringMVC)

【3】BeanPostProccesor(后置处理Bean)(AOP底层实现)  

5.注入(Injection)
定义:通过Spring的配置文件为对象的成员变量赋值;
① 为实体类中的成员变量提供get/set方法
② 在bean标签中添加两个标签

例:<bean id="usr" class="com.user">/*调用无参构造方法创建类的对象*/
	<property name="id">/*调用前set方法为指定属性赋值*/
	    <value>1</value>
	</property>
	<property name="name">/*指定要赋值的属性*/
	    <value>wangyongqi</value>/*指定属性*/
	</property>
    </bean>

6.set注入详解

① JDK类型成员变量
    【1】8种基本类型+包装类+String
        利用property标签中的value标签使用set方法赋值
	<property name="name">/*指定要赋值的属性名*/
	    <value>wangyongqi</value>/*指定属性值*/
	</property>
    【2】数组类型或List集合的成员变量
        利用property标签中的list标签表示数组  在list标签内部使用value标签代表数组中的一个元素
	<property name="name">/*指定要赋值的属性名*/
	    <list>
	        <value>wangyongqi1</value>/*指定属性值*/
		<value>wangyongqi2</value>/*指定属性值*/
	    </list>
	</property>
    【3】Set集合
	在property标签中使用set标签表示set集合  根据具体的使用情况在set中嵌套相应的标签来赋值
	<property name="name">/*指定要赋值的属性名*/
	    <set>
		<value>wangyongqi1</value>/*指定属性值*/
		<value>wangyongqi2</value>/*指定属性值*/
	    </set>
	</property>
    【4】Map集合
	在property中添加一个map标签  在map中添加entry标签代表其中的一个键值对
    【5】Properties
	特殊的Map:key和value都是String类型  默认有11个键值对
	使用props来表示properties集合  其中写prop标签表示其中的一个键值对
	例:<props>
	        <prop key="键名">值</prop>
	    </props>
	② 用户自建(自定义)成员变量
	    <bean id="userDAO" class="com.yongqi.wang.UserDAOImpl"></bean>
	    <bean id="userService" class="com.yongqi.wang.UserServiceImpl">
		<property name="userDAO">
		    <ref local="userDAO"/>/*引用当前配置文件中创建好的类来给属性赋值    参数为id*/
		</property>
	    </bean>
	    string的配置文件中配置的配置顺序没有任何关系
	③ 构造注入
	    【1】Spring通过构造方法完成对象成员变量的赋值
	        前提:提供有参的构造方法
		<bean id="userService" class="com.baizhi.UserServiceImpl">
		    <constructor-arg>//一对标签代表一个构造参数,标签个数与参数个数一致,赋值顺序与构造方法参数顺序一致
		        xxx  //值的外部标签与值的类型相关
		    </constructor-arg>
		    <constructor-arg>
		        xxxx
		    </constructor-arg>
		</bean>
	    【2】构造方法可以重载
	        如果构造参数个数不同时,可以通过<constructor-arg>标签的个数来进行区分
		如果参数的个数相同时,可以通过<constructor-arg type="int">通过type属性来指定参数类型
	④ 自动注入
	    只适用于自建类型
	    例:<bean id="userDAO" class="xxx.UserDAOImpl"/>
		<bean id="userService" class="xxx.UserServcieImpl" autowire="byName"></bean>
		/*
		    当service中有一个自定义类型UserDAO时,spring会通过autowire自动通过
	    	    属性名查找配置文件中匹配的id同名类  来自动为成员变量完成赋值
		*/
			
7.Spring中的IOC(反转控制、依赖注入)的概念
① IOC(Inverse of control)反转控制
【1】控制:对于成员变量赋值的控制权;
[1]在没有Spring框架时,由代码来负责成员变量的赋值  对于成员变量赋值的控制权由代码完成
[2]在Spring框架中,由配置文件负责对于成员变量的赋值,控制权转移到了配置文件中
【2】反转控制:把对于成员变量赋值的控制权从代码中转移到了配置文件中完成
【3】优点:解耦和
【4】原理:工厂设计模式
IOC的中文直译为反转控制,指的就是将成员变量的赋值由代码完成,改为在配置文件中完成来达到解耦合的作用,
Spring完成这种处理机制,是通过底层的工厂设计模式完成的
② DI(dependencyinjection)依赖注入
【1】注入:通过配置文件为成员变量赋值
【2】依赖:当一个类型需要使用另一个类型是,就意味着他依赖另一个类型,那么就可以把另一个类型作为成员变量,通过spring的配置文件,进行赋值;

8.AOP编程(Aspect Oriented Program)面向切面编程
【1】静态代理设计模式(Proxy)
一个项目最重要的就是Service层  
[1]它的核心功能有:
(1)业务逻辑 (2)DAO层调用
[2]额外功能、附加功能(可有可无)
事务的控制。
日志: 用户重要操作的记录信息
性能检测等等。。。
[3]站在软件设计的角度:不应该在Service中添加附加功能,因为不好维护
站在Service调用者的角度中:应该加入额外功能,最少要在Service中添加控制事务
专有词汇:
原始对象(目标对象):只做核心功能的Service
原始方法:原始对象中的方法,只做核心功能
额外功能:控制事务、日志 等
代理对象 = 原始对象+额外功能+实现与原始对象相同接口
特点:每一个原始类,都要为它创建一个代理类
概念:通过代理类为原始类添加额外功能
优点:利于后续的维护
缺点: (1)造成项目的类过载,不利于项目管理
(2)代理类过多,造成额外功能的代码冗余,不利于项目维护
【2】Spring框架的动态代理
[1]什么是动态代理
以切面为基本单位的程序开发。
切面 = 切入点+额外功能
[2]概念:通过代理类为原始类添加额外功能,切入点决定了代理类中的额外功能添加的位置
[3]优点:利于后续的维护
[4]Spring动态代理的开发步骤
创建原始对象、额外功能、切入点、组装切面
(1)创建原始对象(只做核心功能)
(2)额外功能(Advice 接口)
我们一般不会直接使用Advice接口,而是使用其四个子接口
/*使用这个功能需要引入三个额外jar包  aopaliance.jar  aspetcj.jar  aspetcwave.jar */
MethodBeforeAdvice接口:当需要的额外功能要运行在原始方法之前执行,则实现这个接口
/**
*@param method代表原始对象中的方法   被切入的方法
*@param args  代表这个方法的参数  由于可能有多个参数所以为对象数组
*@param target  代表原始对象
*/
before(Method method, Object[] args, Object target);
继承AfterReturningAdvice类:当需要的额外功能要运行在原始方法之后执行,覆盖这个方法
/**
*@param returnValue 原始方法的返回值
*@param method  额外功能所增加给的那个原始方法
*@param args  原始方法参数
*@param target  代表原始对象
*/
afterReturning(Object returnValue, Method method, Object[] args, Object target);
MethodInterceptor//不是Spring框架定义的接口,是aopalliance 定义的接口
(环绕 arround)当需要的额外功能要运行在原始方法之前、之后都执行,则实现这个接口
/**
*@param invocation 代表原始方法
*@return Object 原始方法的返回值
*/
Object invoke(MethodInvocation invocation){
方法前运行的业务
invocation.proceed(); //调用这个方法代表原始方法运行
方法后运行的业务
}
ThrowsAdvice:当需要的额外功能要运行在原始方法抛出异常时执行,则实现这个接口
这个接口时一个标识性接口:接口没有定义方法 SerialBlob、ThrowsAdvice、Tag 都是标识性接口
需要按照指定格式书写这个接口中的方法
因为在这个实现接口类中的方法最终都会被反射作用
所以实现public void afterThrowing(Excepiton e){}这个方法
参数为  原始方法抛出的异常

通过实现这些接口来表达额外功能运行的位置

        【3】配置切入点(PointCut)
决定了额外功能加入的位置//确定额外功能添加在哪一个方法中
例://表示为所有方法执行前全都加入这个额外功能

            <bean id="befor" class="com.yongqi.wang.xxxx  额外功能类"/>
		<aop:config>
		    <aop:pointcut id="pc" expression="execution(* *(..))"/>
		    <aop:advisor pointcut-ref="pc" advice-ref="before"/>
		</aop:config>
            (a)方法切入点(方法)
execution()  切入点函数   参数为切入点表达式
切入点表达式  * *(..)
第一个*表示修饰符与返回值 (不关心修饰符返回值)
第二个*表示方法名 (不关心方法名)
..表示参数表中的值 (不关心参数是什么)
可以理解为不关心  或  所有
例:login方法加入额外的功能  * login(..);
    login(String name)方法  * login(String);
    login(String name,String passwrod)方法  * login(String,String)
    或者 * login(String,..)
注意:在匹配参数时,如果参数类型不再java.lang包中,则不需使用权限定名表示
例: * login(com.yongqi.wang.entity.User);
    (b)类切入点
一级包下(只有一个包)
* *.UserServiceImpl.*(..)
多级包(在多个包下)
* *..UserSreviceImpl.*(..)
    (c)包切入点(常用)
        * com.yongqi.wang.*.*(..)//跟import语句一样只导入当前包下的类
* com..*.*(..)//导入com包下的所有子包下面的所有类
    (d)其他方法切入
        args(String,String) //简化版切入方法  不关心方法名 包名 类名   只要是两个String参数的方法都切入
包与类的信息  替换execution()方法
within(*..UserServcieImpl) //简化版切入方法  不关心这个类到底在哪个包中只关心类是谁
within(com.yongqi.wang..*)  //简化版切入方法  不关心类有多少子包  为所有子包中的所有类中的所有方法都切入
@annotation() //把用户指定的注解作为切入点   有注解就切入  没有就不切入
///自定义一个注解类  在要切入的方法上面加上  @注解类名  
在配置文件中例:expression="@annotation(注解类的权限定名)"
    (e)切入点函数的逻辑运算
        与  或  非    and  or  not
相同的切入点函数不能用and  只能用 or 
        【4】组装(切入点+额外功能)
如何获得动态代理类:
    Spring会通过动态字节码技术,在程序运行的时候,自动创建动态代理类
代理类:
通过原始对象的ID值获得代理对象
代理对象 = ctx.getBean("原始对象id");
【5】Spring AOP 编程的实现原理
    (1)动态代理类如何创建出来的
    底层通过动态字节码技术,创建出来的代理类
    代理:从新实现原始对象的接口,加入额外功能
【6】BeanPostProcessor后置处理Bean
为什么拿原始对象的ID会访问代理对象:这就是后置处理
作用:把工厂对象进行加工之后再交给调用者    实现这个接口  和接口中的两个方法//加工两次
*第一个方法代表工厂创建对象后初始化之前调用加工
*第二个方法代表工厂初始化对象被调用前调用加工
如果没有初始化方法那么实现一个方法就可以

例://模拟AOP 1.3后置处理

public class Bean{
	private List<String> methodNames;  //  get/set
	public boolean isContaintMethodName(String methodName){
		for(String methodN:methodNames){
			if(methodName.equals(methodN)){
				return true;
			}
		}
		return false;
	}
	public Object postProcessAfterInitialization(final Object bean,String arg1)throws BeansException{
		InvocationHandler handler = new InvocationHandler(){
			@Override
			public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
				Object ret = null;
				if(isContaintMethodName(method.getName())){
					System.out.println("...");
					ret = method.invoke(bean,args);
				}else{
					ret = method.invoke(bean,args);
				}
				return ret;
			}
		};
	}
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值