学习spring第三天的总结

学习spring第三天的总结

一.Spring框架概述

1.Spring框架的概述
Spirng是一个service层的框架,可以整合许多其它框架进行工作
spring的主要技术是IOC(DB) AOP
IOC(DI)控制反转
AOP-面向切面编程
2.为myeslipe配置Spring的约束
a.将Spirng的约束文件交给MyEclipse管理:
1)将spring压缩包解压。
2)打开window/preferences,配置其中的XML Catlog
3)add,导入文件xsd文件,通常在自动识别的名称后面加上文件名
b.通过xml玉树文件自动生成服务约束格式的xml:
c.配置xml模板,用来快速生成xml

二.SpringIOC

1.IOC(DI)控制反转(依赖注入)
将对象的创建的权力及对象的生命周期的管理过程有spring框架来处理,从此在开发过程中不再需要关注对象的创建和生命周期的管理,而是需要时由spring矿建来提供,这个有spring框架管理对象和创建和生命周期的机制称之为控制反转。
在创建对象的过程中spring可以依据配置对对象的属性进行设置,这个过程称之为依赖注入

2.IOC的入门案例
a.下载Spring
访问SQpring官网,下载Spring相关的包
b.解压
c.创建项目
d.导包
e.创建配置文件
f.创建按bean类,并在spring中进行配置交由spring来管理
g.在程序汇总通过Spring容器获取对象并使用

3.IOC的实现原理
在初始化一个spring容器时,spring会去解析制定的xml文空间,当介休到其中的标签式会根据该标签中的class属性制定的累的全路径名,通过反射创建该类的对象,并将该对象在内置的map中管理。其中键就是该标签的id值,值就是该对象。
之后,当通过getBean方法来从容器获取对象时,其实就是根据传入的条件在内置的map中是否有匹配的键值,如果有则将该键值对中保存的对象返回,如果没有匹配到则抛出异常。
获取同一个id 的bean,得到的僵尸同一个对象

4.IOC获取对象的方式
传入id值
传入 class值
尽量使用id获取bean

5.别名标签

6.Spring创建对象的方式
a.通过类的午餐构造穿件对象。
在入门案例中使用的就是这种方式。当用最普通的发放时配置一个时,默认就是采用类的无参构造创建对象。在spring容器初始化时,通过<bean<上配置的class属性反射得到字节码对象,通过newInstance()创建对象
class c=class.forName(“类的全路径名称”)
Object obj= c.newInstance()
注意:这种方式下spring创建对象,要求;类必须有无参的构造,否则无法通过反射创建对象,会抛出异常。
ApplicationContext context= new ClassPathXmlApplicationContext(“applicationContext.xml”);
person p=(person)context.getBean(“person”);
b.通过静态工厂创建对象。
需要先写好静态工厂。
xml文件的配置和无参构造相似,需要配置id和地址,不过多一个factory-method

c.实例工厂同上
d.Spring工厂创建对象。
spring内置了工厂接口,可以通过继承FactoryBean接口,使创建步骤与无参一致。

7.单例和多例
单例:singleton
多例:prototype
8.懒加载机制
懒加载机制只对单例bean有作用,对于多例bean设计懒加载没有意义

9.配置初始化和销毁的方法
init-method=“init”
destroy-method=“destroy”

**Spring中关键方法的执行顺序
在spring创建bean独享时,先创建对象(通过无参构造或工厂),之后立即调用init方法来执行初始化操作,之后ban就可以拿来调用其他普通方法,而在对象销毁之前,spring容器调用其destory方法来执行销毁操作。

三.SpringDI
1.IOC(DI)控制反转(依赖注入)
2.set方法注入
通常javabean属性都会私有化,而对外暴露setxxx() getxxx()方法,此时spring可以通过这样的setxxx方法将属性的值注入对象

a.商品spring内置的可直接注入类型的注入

xxx

b.非spring内置的可以直接注入类型的注入
同上

3.基于构造方法的注入
独一香属性设置的另一种方式是在对象创建的过程中通过构造方法传入并设置对象的属性。spring也可以通过这样的构造方法实现属性的注入。

    <bean id="student" class="cn.tedu.beans.Student">
            <!-- 
                    index:为构造方法的第几个参数 进行配置
                    name:为构造方法的哪个名字的参数进行配置
                             **index 和 name 可以配置任何一个或同时配置 但要求一旦配置必须正确
                             **推荐优先使用index方式配置 防止没有源码造成name无法匹配到对应参数
                    type:该构造方法参数的类型
                    value:该构造方法参数的值 ,用来指定基本值
                    ref:该构造方法参数的值,用来指定引用其他bean的值
             -->
            <constructor-arg index="0" name="id" value="999"/>
            <constructor-arg index="1" type="java.lang.String" value="张无忌"/>
            <constructor-arg name="dog" ref="dog"/>
    </bean>

4.自动装配
在spring的set方式实现的注入过程中,支持自动装配机制,所谓自动装配机制没回根据要配置的javabean属性的名字 或类型到spring中自动寻早对应id或类型的bean进行设置,从而省去一次配置的过程,简化了配置。
为制定bean开启自动装配
autowire=“byName”
autowire=“bytype”
为全局配置自动装配
default-autowire=“byName”
default-autowire"=“bytype”
byType
方式根据类型进行陪陪,可能匹配到多个bean,此时会抛出异常。而buyname是根据id来寻找bean,id没有重复,不会有这方面的问题,所以推荐使用byname方式。

四.注解回顾
1.注解概念
2.jdk内置注解
3.自定义注解开发
a.开发一个注解类
开发一个注解类的过程,非常类似于开发一个接口,只不过需要通过@interface关键声名
b.使用元注解修饰注解的声明
所谓元注解是用来修饰注解声明的注解,可以控制被修饰的注解的特性
i.@Target
用来声明被修饰的注解可以用在什么位置
可以在@Target的属性中设置ElementType类型的数据来指定可以使用的位置。如果不用此元注解的修饰,默认注解可以用在任意位置
ii.@Retention
用来声明被修饰的注解会被保留到什么阶段
可以再改注解的属性中通过TetentionPolicy类型的值来制定注解被保留到何时
a)RetentionPolivy.SOURCE
此注解将会被保留到源码阶段,.java中,在编译过程中被删除。此种类型的注解通常是给编译器看的。
b) RetentionPolicy.class
此注解将会被保留在源码阶段和编译阶段,.java和.class中,在类加载的过程中被删除。
这种类型的注解通常是给类加载器看的。
c)RetentionPolicy.RUNTIME
此注解将会被保留在源码阶段、编译阶段和运行阶段,.java .class和内存中的字节码中都会存在。
这种类型的注解通常用来在运行阶段进行反射,控制程序运行过程。
只有RUNTIME级别的注解才可以通过反射技术进行反射。
iii.@Dovumented
用来声明被修饰注解是否要被文档提起工具提取到文档中。
默认不提取。
iv.@inherited
被修饰的注解是否具有继承性
默认没有继承性
c.为注解增加属性
注解类汇总还可以声明属性,为注解类声明属性的过程非常类似于接口定义方法。
但要求,注解中的书友属性必须是public的,可以显示声明,也可以不声明,不声明就是public的
注解中的属性只能是八种基本数据类型String类型 class类型 其他注解类型 及以上类一维数组
注解中声明的属性 需要在使用注解时 为其赋值 赋值的方式 就是使用注解时 再注解,一对小括号 在其中通过属性名=属性值的方式制定属性的值
也可以在声明注解时 在注解的属性后通过default关键字 声明属性的默认值 声明过默认值的属性 可以再使用注解时 不赋值 则默认采用默认值 也可以手动赋值 覆盖默认值 如果属性是一维数组类型,而在传入的数组中一个值 则包括数组的大括号可以省略
如果注解的属性 只有一个需要赋值 且该属性的名称叫做value 则在使用注解时 value=可以不写
4.反射注解
RetentionPolicy.RUNTIME几倍的注解会博爱六道运行,可以通过反射技术获取,从而可以根据是否有注解或注解属性值的不同控制程序按不同方式运行
一下反射相关的类型中都提供了反射注解的方法:
类CLass、类Method、类Constructor、类Package

boolean isAnnhotationPresent(Class<? extedns Annotation>annotationClass) 如果制定类型的注释存在于此元江苏上,则返回true,否则返回false。

getAnnotation(Class annotationClass)如果存在该元素的制定类型的注解,则返回这些注释,否则返回null。
Annotation getAnnotation() 返回此元素上存在的所有注释
b.反射注释案例
package cn.tedu.test;

improt java.lang.annotation.ElementType
improt java.lang.annotation.Retention
improt java.lang.annotation.Retention.TetentionPolicy;
improt java.lang.annotation.Target;

@Target(ElementType.Type)
@Retention(RetentionPolicy.RUNTIME)
@Interface level{
String value();
}

@level(“刑警”)
class Police{
}

public class AnnoTest02{
public static void main(String[] args){
system.out.print(“敬了个礼,您好,您超速了,罚款200元。。。”);
if(Police.class.isAnnotationPresent(level.class)){
level anno=Police.class.getAnnotation(level.class);
if(“协警”.equals(anno.value()){
System.out.println(“哥们少罚点,250块得了~~”);
}else(“刑警”.equlals(anno.value()){
system.out.println("哥们抽根烟,这是200块,收好我走人 ");
}else if{“刑警”.equals(anno.value()){
system.out.println(“赶紧交钱走人,别查出别的事。。。”);
}else{
system.out.println(“xxx”);
}else{
system.out.print(“打一顿,扭送警察局。。”);
}
}
}

五.Spring注解方式 实现IOC和DI
1.注解概念
2.spring中的注解
3.使用类注解
在spring的配置文件中,开启包扫描,制定spring自动扫描哪些个包下的类
<context:component-scan base-package=“cn.tedu.beans”/>
b.使用注解注册bean
@Component
pyblic class Person{
}
c.bean 的id
4.使用属性注解
使用属性注解,可以为bean配置属性的注入过程,省去了在配置文件中进行注入配置的过程,更加便捷
a.在配置文件中开启属性注解功能
context:annotation-config</context:annotation-config>
b.使用属性注解注入bean类型数据。
在bean中的属性上通过如下注解声明属性注入
@Autowired
也可以使用@Qualiofier(value=“dao1”)注解,明确的制定,要注入哪个id的bean
@Autowired
private Dog dog;

c.属性注入bean类型数据的原理:
当spring容器解析xml时,发现开启了属性注解,则会在创建bean时,检测属性上是否存在,@Autowired注解,如果发信啊该注解,则会通过当前属性的名称寻找是否存在该id 的bean,如果存在则注入进来,如果不存在,再检查和当前属性相同的bean,如果有则注入捡来,如果没有则抛出异常

**也可以使用@Resource(name=”id")制定注入给定id的bean,但是不建议大家使用
d.spring中可以通过注解方式注册bean,并可以通过@Autowired实现属性的自动注入,但注入的都是自定义的bean;类型,如果累中包含例如long String等spring内置可注入的类型是,又该如何注入呢?可以使用@Value来实现注入
@Value(“zs”)
private String name;
这种方式可以实现spring内置类型的注入,但是这种方式将注入的值写死在了代码中,后续如果希望改变注入的初始值,必须来修改源代码,此时可以讲这些值配置到一个properties配置文件中,再在spring中进行引入。
e.spring内置支持注入类型的注解方式的注入,再通过value引入
配置过程:
将spring-util-3.2.xsd交给myeclipse管理
在当前spring容器的配置文件中导入util名称空间
再通过适当的util标签注册数据
5.其他注解
a.Scope(value=“prototype”)
配置修饰的累的bean是单例还是多例, 如果不配置默认为单例。
@Component
@Scope(”prototype")
public class Dog{
}
b.@lazy
配置修饰的类的bean采用懒加载机制
c.PostConstruct
在bean对应的累中,修饰摸一个方法,该方法声明为初始化方法,对象创建之后立即执行
d.@ PreDroy
在bean对应的类中,修饰某个方法 将该方法声明为销毁的方法,对象销毁之间调用的方法
e.2Conrolller @Service @ Repository @Component
这四个注解的完全相同的,都是用来修饰类,将类声明为Spring管理的bean的。
其中@Component一般认为是通用的注解
而@Controller用在软件分层中的控制层,一般用在web层
而@Service用在软件分层中业务访问层,一般用在service层
而@Repository作用在软件分层中的数据访问层,一般用在dao层

六.使用spring IOC DI实现软件分层
1.软件分层思想回顾
2.Spring IOC DI改造EasyMall
在程玉成之间设计接口,面向接口编程:
不在直接创建对象,而是通过spring注入
如果存在多个实现类,则通过制定名称证明的id,实现使用制定实现类的bean:
在spring中,如果自动装配一个接口,默认会先通过属性名找对应id的bean,如果找不到就会去寻找是否存在在该接口的实现类的bean,如果存在且只存在一个,则会将该bean注入,如果不尊在或存在多个,则抛出异常

七.利用springAOP基础-代理设计模式
1.改造过后的EasyMall的问题
改造过后的EasyMall成功结局了耦合的问题,但是在很多地方仍然存在非该层应该事先的功能,早成了无法"高内聚"的现象,同时存在大量重复代码,卡法效率低下
此时可以通过代理设计模式,将这部分代码提取到代理者中,简化层中的代码
2.静态代理模式
静态代理设计模式特点:
优点:
结构清晰 易于理解
缺点:
如果被代理者有多个方法,则代理者也需要开发啊多个方法,其中往往存在大量重复代码,仍然存在代码重复
静态代理设计模式解决了软件分层过程中,额外的功能代码侵入模块的问题,将额外的功能代码提取到了代理者中进行,但是静态代理实现的代理者中存在大量重复的代码,并没有结局代码重复问题。所以在真正开发中–包括spring的底层,基本不会使用静态代理
3.动态代理
在jdk中提供了动态代理实现的工具类,直接使用该工具类就可以创建出代理者,并且可以通过内置的回调函数制定代理在工作时的执行逻辑,从而实现基于jdk原生api的动态代理机制。
java.lang.reflect
类Proxy
java.lang.Object
static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
返回一个制定接口的代理类实例,该接口可以讲方法调用指派的调用处理程序

案例:
package cn.tedu.javaproxy;

import java.lang.reflect.InvocationHandler;
improt java.lang.reflect.Method;
import java.lang.reflect.Proxy;

improt org.junit.Test;

pyblic class JavaProxyTest{
@Test
public void test01(){

//被代理者
final FBB fbb-=new FBB();

//java动态代理方式 生成fbb的代理者
classLoader:用来生成代理者类的类加载器,通常可以传入被代理者类的类加载器
interfaces:要求生成的代理者实现的接口们,通常就是实现和被代理者相同的接口,保证具有和被代理者相同的方法
invcationHandler:用来设定回调函数的回调接口,使用者需要写一个类实现此接口,从而实现其中的invoke方法
在其中编写代码处理代理者调用方法是的回调过程,通常咋i这里调用真正对象身上的方法,并且在方法之前或之后做额外操作。
SJSkill proxy=(SJSKill)
Proxy.new ProxyInstance(FBB.class.getClassLoader(),Fbb.classs.gettInterfaces(),newi InvocationHandeler(){
@Overrride
public Object invoke(Object proxy,Mehod method,Object[] args)throw Throwable{
if(“拍电影”.equals(method.getName()){
System.out.println("不好意思,给多少钱不拍了~~“)
return null;
}else{
System.out.prinln(“检验权限。。。。”);
Object returnObj=method.invoke(fbb,args);
System.out.println(“记录日志。。。。”);

return returnObj;
}
}
});
proxy.吃();
proxy.唱歌();
proxy.拍电影();
}
}

1.改造过后的EasyMall的问题
2.静态代理模式
静态代理设计模式特点:
优点:
结构清晰 易于理解
缺点:
如果被代理者有多个方法,则代理者也需要开发多个方法,其中往往存在大量重复代码,仍然存在代码重复
静态代理设计模式
3.动态代理-jdk内置的动态代理

java动态代理的特点:
优点:
不需要像静态代理一样被代理方法都要实现一遍,而值需要咋i回调函数中处理就可以了,重复代码只需编写一次
缺点:java的动态代理是通过代理者实现和被代理者相同的接口来保证两者具有相同的方法的,如果被代理者想要被代理的方法不属于任何接口,则生产呢过的代理者自然无法具有这个方法,也就无法实现对该方法的代理。
所以java的动态代理机制是基于接口进行的,手指于要代理的方法是否有接口的支持
4.动态代理-第三方包cglib实现的动态
CGTLIB是第三方提供的动态代理的实现工具,不管哟没有接口都可以实现动态代理。
CGLIB实现动态代理的原理是 生成的动态代理是被代理者的子类,所以代理者具有和父类即被代理者相同的方法,从而实现代理。
a.导入CGLIB相关包
之前导入的spring包中就包含了CGLIB
spring-core-3.2.3.RELEASE.jar
//增强器
Enhancer enhancer=new Enhancer();
//设定接口–此方法要求生成的动态代理额外实现制定接口们,但cglib动态代理不是靠接口实现的,所以可以不设置
enhancer.setinterfaces(fbb.getClass().getinterfaces()):
设定父类–此处要传入被代理的累,cglib是通过集成被代理者的类来持有和被代理者相同的方法的,此方法必须设置。
enhancer.setSuperclass(fbb.getClass());

//设定回调函数–为增强器设定回调函数,之后通过增强器生成的代理独享调用任何方法法都会走到此回调函数中,实现调用真正被代理对象的方法的效果。
enhancer.setCallback(new MethodInterceptor(){}

CGLIB冬天代理的特点:
优点:无论是否有接口都可以实现动态代理,使用场景基本不受限
缺点:第三方提供的动态代理机制,不是原生的,需要导入第三方开发包才可以使用

5.使用代理改造EasyMall
使用代理gaizaoEasyMal,将功能代码提取到代理者中,实现“高内聚”的效果

八.springAOP详解
1.Spring aop中的基本概念

连接点(JoinPoint):在程序执行中某个特定的点,比如方法调用的时候或者处理异常的时候。在Spirng AOP中,一个连接点重视表示一个方法的执行。
通俗讲:
层与层之间调用的过程中,目标增中可供调用的方法,就称之为连接点

切入点:
在连接点的基础上 ,增加上切入规则,选择出需要进行增强的切入点,这些基于切入规则选出来的连接点,就被称之为切入点

切面:
通俗讲:
下一上就是的那个spring拦截下切入点之后将这些切入点交给处理类进行功能的增强,者个处理类就称之为切面
广义上来讲 将spring底层的代理 切入点和处理类加载一切实现的对层与层之间调用过程进行增强的机制称之为切面

通知:在切面的某个特定的连接点上执行的动作。其中包括了around、before和after等不同类型的通知,(通知的类型将在后面部分进行讨论。)许多AOP框架(包括Spring)都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链
通俗讲:在spring底层的代理拦截下切入点后,将切入点交给切面类,切面类中就要有处理这些切入点的方法,折现方法就称之为通知(也叫增强 增强方法)。这对于切入点执行的过程,通知还分为不同类型,分别关注切入点在执行过程中的不同时机。

目标对象:
通俗讲:
就是真正希望被访问的对象,spring底层的动态代理对他进行了代理,具体能不能真正的访问到目标对象,或在目标对象真正执行之前和之后是否做一些额外的操作,取决于切面。

2.spring的aop入门案例
a.导入aop相关开发包
b.创建一个切面类
c.定义通知
d.定义一个连接点
e.配置切入点
f.定义切面
g.执行方法,发现切面确实起作用

3.切入点表达式
a.within表达式
通过类名进行匹配 粗粒度的切入点表达式
within(包名.类名)
则这个类中所有的方法都会被表达式识别,称为切入点、
<aop:pointcut expression=“within(cn.tedu.service.UserServiceImpl)”
在within表达式中可以使用号匹配符,匹配指定包下所有类,注意,之匹配当前包
<aop:point expression="within(cn.tedu.service.
)" id=“pc01”/>
b.execution()表达式
语法:extcution(返回值类型 包名.类名. 方法名(参数类型,参数类型))

4.SpringAOP的原理
Spring会在用户获取对象时,生成目标对象那个的代理对象,之后根据切入点股则,匹配用户连接点,得到切入点,当切入点被调用时,不会直接去寻找目标独享,而是通过代理喜爱给你拦截之后交由切面类中的制定的通知执行来进行增强

Spring自动为目标对象生产呢过代理对象,默认情况下,如果目标独享实现过接口,则采用java的动态代理机制,如果目标对象没有实现过接口,则采用cglib动态代理。开发者可以再spring中进行配置,要求无论目标对象是否实现过接口,都轻质使用cglib动态代理

5.Spring的五大通知类型

a.在目标方法执行之前执行执行的通知
前置通知方法,可以没有参数。也可以额外接受一个JoinPoint,Spring会自动将该对象传入,代表当前的连接点,通过该对象可以获取目标兑现和目标方法相关的信息。
注意,如果接受JoinPoint,必须抱枕其为方法的第一个参数,否则报错
b,环绕通知
在目标方法执行之前和之后都可以执行额外代码的通知。
在环绕通知中必须显示的调用目标方法,目标方法才会执行,这个显示调用时通通过ProceedingJoinPoint来实现的,可以砸i环绕通知汇总接受一个此类型的形参,spring容器会自动将该对象传入,注意这个参数必须处在环绕通知的第一个形参位置。
要注意,只有环绕通知可以接受ProceedingJoinPoint,而其他通知只能接受JoinPoint。
环绕通知需要返回返回值,否则真正调用者将拿不到返回值,只能得到一个null。
环绕通知有
控制目标方法是否执行、控制是否返回值、甚至改变返回值的能力。
环绕通知虽然有这样的能力,但一定要慎用,不是技术上不可行,而是要小心不要破坏了软件分层的"高内聚,低耦合"的目标。
c.后置通知
在目标方法执行之后执行的通知。
在后置通知中也可以选择性的jiehso7u一个JoinPoint来获取连接点的额外信息,但是这个参数必须处在参数列表的第一个。
在后置通知中,还可以通过配置获取返回值。
一定要保证JoinPoint处在参数列表的第一位,否则抛异常
d.异常通知;
在目标方法抛出异常时执行的通知。

九.SpringAOP案例
1.异常信息收集
2.统计业务方法执行的时间
3.实现事务控制
4.通过aop进行权限控制

十.Spring整合JDBC
1.回顾JDBC
2.Spring整合JDBC
3.Spring中JDBC模板类
4.声明式事务处理
5.声明式事务处理-注解方式
6.拓展案例

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值