spring-02

bean元素的继承:在bean的配置中有相同的配置,可以提取一个单独的bean,然后再继承。

spring-02_第1张图片

spring-02_第2张图片

上述两个类,有相同的属性:dataSource.
 意味着在xml中做配置的时候,都得配置dataSource属性.

spring-02_第3张图片


通过上述代码,我们发现两个问题:
  1):多个元素可能有相同的元素配置.--->bean元素的继承方式.
    
  2):在Java类中,属性(setter)也是重复的.

spring-02_第4张图片



手动装配(注解方式)

Springf提供的装配标签:
Autowired和Qualifier标签:

1.通过@Autowired标签可以让Spring自动的把属性需要的对象从Spring容器找出来,并注入给该属性。
2.第三方程序:Spring3.0之前,需要手动配置@Autowired解析注解程序,Spring就会自动的加入针对@Autowired标签的解析程序。从Spring3.0开始,可以不再需要改配置了。如果不在Spring的测试环境中,也找到@Autowired的解析代码,此时页必须配置.
   
3.@Autowired标签贴在字段或者setter方法上。
4.@Autowired可以同时为一个属性注入多个对象。
      public void setXxx(OtherBean1 other1,OtherBean2 other2) {}
5.使用@Autowired标签可以注入Spring内置的重要对象,比如BeanFactory,ApplicationContext。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class SpringTest {
    @Autowired
    private ApplicationContext ctx;
}
6.默认情况下@Autowired标签必须要能找到对应的对象,否则报错。不过,可使用required=false来避免该问题:@Autowired(required=false)
7.@Autowired找bean的方式:
    1)、首先按照依赖对象的类型找,如果找到则使用setter方法或者字段直接注入;
    2)、如果在Spring上下文中找到多个匹配的类型,再按照名字去找,如果没有匹配则报错;
    3)、可以通过使用@Qualifier("otherBean

spring-02_第5张图片


spring-02_第6张图片


JavaEE提供的属性注入标签:

JavaEE提供的装配标签:
  @Resource标签:
  1,@Resource标签是JavaEE规范的标签;
  2,@Resource标签也可以作用于字段或者setter方法;
  3,也可以使用@Resource标签注入一些spring内置的重要对象,比如BeanFactory.ApplicationContext;
  4,@Resource必须要求有匹配的对象;
  5,既引入了@Autowired标签的解析器,也引入了@Resource的解析器;
  6,@Resource标签找bean的方式:
    1),首先按照名字去找,如果找到,就使用setter或者字段注入;
    2),如果按照名字找不到,再按照类型去找,但如果找到多个匹配类型,报错;
    3),可以直接使用name属性指定bean的名称;但是,如果指定的name,就只能按照name去找,如果找不到,就不会再按照类型去找;

    @Resource(name="otherBean2")
    private OtherBean2 other2;
等价于
    @Autowired

    @Qualifier("otherBean2")

@autowired和@Resource的对比:

1,@Autowired:是Spring定义的标签,所以不太稳定,并且对象和spring框架关联(Spring对我们的代码有侵入);
2,@Resouce:是J2EE的规范,所以稳定,在J2EE规范容器中也能正常使用;
-------------------------------------
开发中是使用XML配置还是注解配置,使用注解是使用Autowired还是Resource.
-------------------------------------
使用XML好处: 清晰,可以集中管理.
使用注解:  简单/快速/高效

使用注解简化IOC:

同样的,使用IOC注解一样配置解析器

    使用context:component-scan来扫描spring需要管理的bean
    base-package就告诉spring,去哪些包及其子包里去扫描bean,如果有多个包需要被扫描;只需要用逗号隔开多个包即可
    


2.标注Bean的注解:@Component
  默认情况,直接使用类的名字(首字母小写作为bean的名字)
  如果要修改bean的名称;直接使用value属性来重新定义bean的名称
  @Component("otherbean")
  public class OtherBean {}

2.标注Bean的注解:@Component
  默认情况,直接使用类的名字(首字母小写作为bean的名字)
  如果要修改bean的名称;直接使用value属性来重新定义bean的名称
  @Component("otherbean")
  public class OtherBean {}

4.bean组件版型标签
  bean组件版型:
  @Service用于标注业务层组件、
  @Controller用于标注控制层组件(如struts中的action)、
  @Repository用于标注数据访问组件,即DAO组件。
  @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

5.指定bean的作用域:@Scope("prototype")
6.初始化和销毁方法
  @PostConstruct
  public void init() {
  相当于
  @PreDestroy
  public void destory() {
  相当于

7.选用xml还是注解:
  1),Annotation:使用方便,XML文件很小,但是,依赖关系又重新回到了代码当中;
  2),XML:使用稍微复杂,但是,代码很干净,代码不会很任何框架产生关系;XML安全;
  两种方式都必须掌握;

spring-02_第7张图片

spring-02_第8张图片

用一个简单的模拟注册功能,体验一个注解配置:

spring-02_第9张图片

spring-02_第10张图片

spring-02_第11张图片

spring-02_第12张图片

装饰设计模式:

装饰设计模式:在不必改变源代码基础上,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是包裹真实的对象。说的直白点,就是对已有对象进行功能增强!

spring-02_第13张图片

ps:这种模式暴露了对象,不安全。

静态代理模式:

代理模式:客户端直接使用的都是代理对象,不知道真实对象是谁,此时代理对象可以在客户端和真实对象之间起到中介的作用。
1、代理对象完全包含真实对象,客户端使用的都是代理对象的方法,和真实对象没有直接关系;
2、代理模式的职责:把不是真实对象该做的事情从真实对象上撇开——职责清晰;
静态代理(proxy):在程序运行前就已经存在代理类的字节码文件,代理对象和真实对象的关系在程序运行前就确定了。

动态代理(proxy):动态代理类是在程序运行期间由JVM通过反射等机制动态的生成的,所以不存在代理类的字节码文件。代理对象和真实对象的关系是在程序运行时期才确定的。

静态代理也就是把业务方法对象注入到一个类中,并在这个类中创建方法对业务方法增强,这个类就是代理类。

spring-02_第14张图片

第一种xml的写法:

spring-02_第15张图片

第二种XML的写法:

spring-02_第16张图片

对于静态代理优缺点的分析:
优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性。

缺点:

1.代理对象的某个接口只服务于某一种类型的对象,也就是说每一个真实对象都得创建一个代理对象。

2.如果需要代理的方法很多,则要为每一种方法都进行代理处理。

3.如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
---------------------------

如果期望一个代理类就可以代理多个真实对象------->动态代理.


JDK的动态代理

动态代理类是在程序运行期间由JVM通过反射等机制动态的生成的,所以不存在代理类的字节码文件。代理对象和真实对象的关系是在程序运行事情才确定的。

JDK动态代理API分析:
1、java.lang.reflect.Proxy 类:
Java 动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
主要方法:
public static Object newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler hanlder)
方法职责:为指定类加载器、一组接口及调用处理器生成动态代理类实例
参数:
   loader        :类加载器
   interfaces    :模拟的接口
   hanlder        :代理执行处理器
返回:动态生成的代理对象

2、java.lang.reflect.InvocationHandler接口:
public Object invoke(Object proxy, Method method, Object[] args)
方法职责:负责集中处理动态代理类上的所有方法调用
参数:
    proxy    :生成的代理对象
    method    :当前调用的真实方法对象
    args        :当前调用方法的实参
返回: 真实方法的返回结果

jdk动态代理操作步骤
① 实现InvocationHandler接口,创建自己增强代码的处理器。
② 给Proxy类提供ClassLoader对象和代理接口类型数组,创建动态代理对象。
③ 在处理器中实现增强操作。

spring-02_第17张图片

测试类:

spring-02_第18张图片

原来的业务方法:

spring-02_第19张图片


动态代理的XML配置:

spring-02_第20张图片


JVM动态代理的优缺点分析:

JDK动态代理存在的问题:
JDK动态代理:
1,代理的对象必须要实现一个接口;
2,需要为每个对象创建代理对象;
3,动态代理的最小单位是类(所有类中的方法都会被处理);
---------------------------------
JDK动态代理总结:
1,JAVA动态代理是使用java.lang.reflect包中的Proxy类与InvocationHandler接口这两个来完成的。
2,要使用JDK动态代理,必须要定义接口。

3,JDK动态代理将会拦截所有pubic的方法(因为只能调用接口中定义的方法),这样即使在接口中增加了新的方法,不用修改代码也会被拦截。

4,如果只想拦截一部分方法,可以在invoke方法中对要执行的方法名进行判断。

CGLIB动态代理:

CGLIB动态代理:
原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

spring-02_第21张图片

spring-02_第22张图片


CGLIB代理总结:


1,CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。

2,要求类不能是final的,要拦截的方法要是非final、非static、非private的。

3,动态代理的最小单位是类(所有类中的方法都会被处理);


JVM动态代理和CGLIB的选择:

在Spring中:

若目标对象实现了若干接口,Spring就会使用JDK动态代理。

若目标对象没有实现任何接口,Spring就使用CGLIB库生成目标对象的子类。

对接口创建代理优于对类创建代理,因为会产生更加松耦合的系统,也更符合面向接口编程规。

cglib和javassist代理的机制都是一样的,都是通过继承实现的.


AOP概念:什么叫做AOP:Aspect oritention programming(面向切面编程)

上面的两种代理操作可以实现代理操作,但是每个service都需要去配置比较麻烦。

AOP的介绍:

AOP的目的:
AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,
便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

AOP的优势:
降低模块的耦合度、使系统容易扩展、更好的代码复用性.
Spring的AOP使用动态代理实现:
如果一个类实现了接口,那么spring就使用JDK的动态代理完成AOP;
如果一个类没有实现接口,那么spring就是用cglib完成AOP;

AOP当中的概念:
1、切入点(Pointcut):在哪些类,哪些方法上切入(where);
2、增强(Advice):    早期翻译为通知,在方法执行的什么时机(when:方法前/方法后/方法前后)做什么(what:增强的功能);
3、切面(Aspect):    切面=切入点+通知,通俗点就是:在什么时机,什么地点,做什么增强!
4、织入(Weaving):   把切面加入到对象,并创建出代理对象的过程。(该过程由Spring来完成)。

XML的方式实现AOP:

AOP的规范本应该由SUN公司提出,但是被AOP联盟捷足先登.AOP联盟制定AOP规范,首先就要解决一个问题,怎么表示在哪些方法上增强—— AspectJ(语言)。
AspectJ切入点语法如下(表示在哪些包下的哪些类的哪些方法上做切入):
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?    
            name-pattern(param-pattern)throws-pattern?)

翻译成中文:
execution(<修饰符>? <返回类型> <声明类型>? <方法名>(<参数>) <异常>?)
举例:
public static Class java.lang.Class.forName(String className)throws ClassNotFoundException
------------------------------------------------------------------------
在所有的业务层方法上做增强:
execution(* com._520it.pss.service.*Service.*(..))

spring-02_第23张图片


1).Spring AOP开发依赖的jar:
spring-aop-4.1.2.RELEASE.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar


2).AOP的命名空间配置:

spring-02_第24张图片

xml的具体配置:

spring-02_第25张图片


spring中的各种增强:

spring-02_第26张图片

各种不同的增强:
aop:before(前置增强):在方法执行之前执行增强;
aop:after-returning(后置增强):在方法正常执行完成之后执行增强(中间没有遇到任何异常);
aop:throwing(异常增强):在方法抛出异常退出时执行增强代码;
aop:after(最终增强):在方法执行之后执行,相当于在finally里面执行;可以通过配置throwing来获得拦截到的异常信息
aop:around(环绕增强):最强大的一种增强类型。 环绕增强可以在方法调用前后完成自定义的行为,环绕通知有两个要求,
                      1,方法必须要返回一个Object(返回的结果)
                      2,方法的第一个参数必须是ProceedingJoinPoint(可以继续向下传递的切入点

具体业务配置:

spring-02_第27张图片

txmanager中的各种增强方法:

spring-02_第28张图片


用注解的方式实现AOP:

用component,实现IOC

@autowired 实现DI

AOP注解:

先在xml中添加解析器:

然后就是AOP三部曲:whate where  when 

whate:@aspect

where:@pointcut  (*execution(.....))在类里面定义一个方法,该方法的名称就是Pointcut的id

public void txPoint(){}

when:@before("txPoint()")  前置增强

            @after ("txPoint()”)  后置增强

            @AfterThrowing(value="txpoint()",throwing="ex")

            @Around("txPoint"); 环绕增强我们需要定义个环绕增强的方法,

public Object allWork(ProceedingJoinPoint pjp){

//pip是代理对象

//这里写前置增强的事务
Object ret;

try(){

    ret=pjp.procee();//底层被代理的方法执行后的返回值

    //这里写after 后置增强的事务

}catch{

    //这里写异常增强的事务

}finally{

//这里写释放资源等事务

}

}



你可能感兴趣的:(spring)