Spring框架知识复习之二

Spring使用注解对Bean进行管理

1 使用注解需配置aop相关xsd文件的约束和命名空间

xsd文件名为:spring-aop-4.2.xsd

2 注解组件扫描配置

示例如下:base-package属性 设置扫描指定包下的所有子孙包
<context:component-scan base-package="cn.itma.bean"></context:component-scan>

3 spring管理bean的常用注解

<1>作用在类上的 用于创建对象的 @Component组件注解 的三个衍生注解(功能一致)

* @Controller  :WEB层
* @Service:业务层
* @Repository:持久层
示例如下
            注解书写:
            package xxx.yyy.test;
            @Component("user")
            @Scope(scopeName="prototype")
            public class  User{
            }
            对应的xml配置书写:
            <bean name="user" class="xxx.yyy.test.User" scope="prototype"/>

<2> 用于属性注入的注解 (使用注解注入的方式,可以不用提供set方法)

* @Value:用于注入普通类型
* @Autowired:自动装配(默认按类型进行装配)
    存在的问题:
    如果匹配多个类型一致的对象,将无法选择具体注入哪一个对象,
    需要加一个注解辅助,声明它要注入哪一个Car对象
* @Qualifier:强制按照名称进行注入。
    存在的问题:
    如果存在多个名称一致的,类型不一致的对象,将无法准确匹配到。
* @Resource:相当于@Autowired和@Qualifier一起使用
示例如下
    注解书写:
    public class User{
        @Value("flower")
        private String name;
        public String getName() {return name;}
        public void setName(String name) {this.name = name;}

    @Resource(name="car")
    private Car c;
}
对应的xml配置书写:
<bean name="user" class="xxx.yyy.User">
    <property name="name" value="flower"/>
    <property name="car" ref="car"></property>
</bean>
<bean name="car" class="xx.bean.Car">
    <property name="name" value="dd"></property>
    <property name="color" value="black"></property>
</bean>

<3>Spring整合junit测试的 注解

 * 导入的包为:spring-test-4.2.4.RELEASE.jar
* @RunWith(SpringJUnit4Cla***unner.class)  --帮我们创建容器
* @ContextConfiguration("classpath:applicationContext.xml") --指定创建容器使用哪个配置文件

<4>设置Bean作用范围的注解

@Scope:
    * singleton:单例
    * prototype: 多例

<4>设置Bean生命周期的注解

@PostConstruct:相当于init-method
@PreDestroy:相当于destroy-method
示例如下
    注解书写:
    public class User{
        @PostConstruct
        public void init(){
            syso("这里是初始化方法");
        }
        @PreDestroy
        public void destroy(){
            syso("这里是销毁方法")
        }
    }
    对应的xml配置书写:
    <bean name="user" class="xxx.yyy.User" init-method="init" destroy-method="destroy">
</bean>

4 spring管理bean的xml方式与注解方式对比

                xml配置                               注解配置
                (1)bean的创建和定义          <bean id="" class=""/>                                               @Component(三个衍生:Controller,Service,Repository)
                (2)bean名称的指定                通过id或name指定                                                     @Component("person")
                (3)bean中参数的注入           通过<property>或p命名空间                                      @Autowired(按类型注入)或@QUalifier(按名称注入)或Resource(两者相加)
                (4)bean生命周期和                通过设置Scope属性,包括: singleton和prototype         @Scope(scopeName="singleton")作用范围的设置

总结:

        xml结构清晰,注解开发方便,所以实际开发中有一种xml和注解开发(Bean有XML配置,但使用的属性用注解注入)。

5 Spring和AOP面向切面编程

1 AOP概述
    AOP(aspect oriented Programming面向切面编程),AOP是OOP(面向对象编程)的延续,
    也是Spring框架的一个重要内容,spring利用AOP可以对业务逻辑各个部分进行隔离,
    降低业务逻辑之间的耦合性,提供程序的重用性和开发效率。
2 Spring中AOP的主要功能
    在不修改源码的基础上,对程序进行增强,可进行权限校验,日志记录,性能监控,事务控制。

3 Spring的AOP底层实现
   两种代理机制:
    * JDK的动态代理:针对实现了接口的类产生代理
    示例:
                //手动实现动态代理--演示(针对的是代理对象和被代理对象的实现同一接口)
                public class UserServiceProxyFactory implements InvocationHandler {
                    private UserService us;
                    public UserServiceProxyFactory() {super();}
                    public UserServiceProxyFactory(UserService us) {super();this.us = us;}

                    public UserService getUserServiceProxy() {
                        //生成  UserService动态代理对象
                        UserService usProxy=(UserService) Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(),
                                UserServiceImp.class.getInterfaces(),
                                this);
                        //返回
                        return usProxy;
                    }

                    //下面为动态代理对象  对原对象的方法加强
                    @Override
                    public Object invoke(Object arg0, Method method, Object[] arg2) throws Throwable {
                        System.out.println("打开事务");
                        Object invoke = method.invoke(us,arg2);
                        System.out.println("提交事务");
                        return invoke;
                    }
                }
    * Cglib的动态代理:针对没有实现的接口的类产生代理,应用的是底层字节码增强技术,生成当前类的子类对象。
        示例:
                //通过第三方实现 代理技术--cglib技术(针对的是代理对象和被代理对象的继承关系)
                public class UserServiceProxyFactory2 implements MethodInterceptor{
                    private UserService us;
                    public UserServiceProxyFactory2(UserService us) {super();this.us = us;}
                    public UserServiceProxyFactory2() {super();}

                    public UserService getUserServiceProxy() {
                        Enhancer en=new Enhancer(); //帮我们生成代理的对象
                        en.setSuperclass(UserServiceImp.class); //设置对谁进行代理
                        en.setCallback(this); //指定代理对象 要增强什么功能(代理要做什么)
                        UserService us = (UserService) en.create(); //创建代理对象
                        return us;
                    }

                    @Override
                    public Object intercept(Object proxyobj, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
                        //打开事务
                        System.out.println("打开事务");
                        //调用原有方法
                        Object returnValue = methodProxy.invokeSuper(proxyobj,arg);
                        //提交事务
                        System.out.println("提交事务");
                        return returnValue;
                    }
                }
4 Spring基于AspectJ的AOP开发
     (1)Spring的AOP开放相关术语:
            <1>Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点.
            <2>Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义
                    &   execution()切入点表达式的基本语法:
                            * 基本格式:execution( [方法访问修饰符] 方法返回值 全类名.方法名(方法参数))
                            * 配置方法名的不同形式:
                               public void cn.itheima.service.UserServiceImp.save()     简单形式
                               void cn.itheima.service.UserServiceImp.save()            public可省略
                               * cn.itheima.service.UserServiceImp.save()              *代表任意的返回值类型
                               * cn.itheima.service.UserServiceImp.*()                 *()代表该目标对象下的所有方法
                               * cn.itheima.service.UserServiceImp.*(..)               *(..)对方法参数不作任何要求(空参和实参都行)
                               //下面为开发常用形式
                               * cn.itheima.service.*ServiceImp.*(..)                  *ServiceImp代表名称包含 ServiceImp的目标对象(是开发的标准形式)
                               * cn.itheima.service..*ServiceImp.*(..)               ..*ServiceImp 代表 在包括service下的子孙包中的  名称包含 ServiceImp的目标对象
                    & 配置AOP切入点示例:
                        <aop:config>
                                id属性:为切入点命名
                                <aop:pointcut expression="execution(* cn.ith.service.*ServiceImp.*(..))" id="pc"/>
                        </aop:config>
            <3>Advice(通知/增强):
                    所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.
                    通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
                        有一种特殊的通知:Introduction(引介)
                            不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.
                    通知类型详解
                        前置通知(before):在目标方法执行 之前.
                        后置通知(afterReturning) :在目标方法执行 之后,如果出现异常则不会调用
                        环绕通知(around) :在目标方法执行 前和后
                        异常抛出通知(afterException):在目标方法执行 出现异常的时候 执行
                        最终通知(after) :无论目标方法是否出现异常 最终通知都会 执行 .
            <4>Aspect(切面): 是切入点和通知(引介)的结合
                    配置切面:
                    <!-- 属性ref:要关联的 通知 名称 -->
                    <!--2.配置通知对象(目标对象的增强版)-->
                    <bean name="myAdvice" class="cn.itheima.d_aspect.MyAdvice"></bean>
                    <aop:aspect ref="myAdvice">
                            <!-- method属性:设置方法名   pointcut-ref:设置要关联的  切点名称-->
                            <!--指定名为before为前置通知-->
                            <aop:before method="before" pointcut-ref="pc"/>
                            <!--指定名为afterReturning为后置通知(出现异常不会调用)  -->
                            <aop:after-returning method="afterReturning" pointcut-ref="pc"/>
                            <!--指定名为around为环绕通知  -->
                            <aop:around method="around" pointcut-ref="pc"/>
                            <!--指定名为afterException为异常拦截通知  -->
                            <aop:after-throwing method="afterException" pointcut-ref="pc"/>
                            <!--指定名为after为后置通知(是否出现异常都会调用)  -->
                            <aop:after method="after" pointcut-ref="pc"/>
                    </aop:aspect>
            <5>Target(目标对象):代理的目标对象
            <6>Weaving(织入):
                  是指把增强应用到目标对象来创建新的代理对象的过程。
                  spring采用动态代理织入,而AspectJ采用编译期织入和类装在期织入.
                  AspectJ是一个面向切面的框架,它定义了AOP语法,扩展了Java语言。
            <7>Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类
     (2)Spring使用AspectJ进行AOP开发
            <1>要导入相关的jar包,如下
                    * spring传统aop开发包:
                        spring-aop-4.2.4.RELEASE.jar
                        com.springsource.org.aopalliance-1.0.0.jar
                    * aspectJ开发包:
                        com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
                        spring-aspects-4.2.4.RELEASE.jar
            <2>导入aop约束
                    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                            xmlns="http://www.springframework.org/schema/beans"
                             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-4.2.xsd
                             http://www.springframework.org/schema/context
                             http://www.springframework.org/schema/context/spring-context-4.2.xsd
            http://www.springframework.org/schema/aop
             http://www.springframework.org/schema/aop/spring-aop-4.2.xsd ">

             <3>配置xml方式实现AOP的代码示例
             示例需求:对一个UserServiceImpl类 进行AOP增强 其save()方法
             * UserService类(目标对象)
                public interface UserService {void save();}
                public class UserServiceImp implements UserService {
                    @Override
                    public void save() {
                        System.out.println("保存");
                    }
                }
            * MyAdvice(通知对象)
                public class MyAdvice {
                        public void before() {
                            System.out.println("前置通知!");
                        }
                        public void afterReturning() {
                            System.out.println("后置通知!(如果出现异常则不会调用)");
                        }
                        public Object around(ProceedingJoinPoint pjp) throws Throwable {
                            System.out.println("这是环绕通知之前的部分!");
                            Object proceed = pjp.proceed();  //调用目标方法
                            System.out.println("这是环绕通知之后的部分!");
                            return proceed;
                        }
                        public void afterException() {
                            System.out.println("出现异常了!");
                        }
                        public void after() {
                            System.out.println("另一个后置通知(目标方法运行之后调用,无论是否出现异常都会调用)");
                        }
                }
            * AOP相关配置
                <!--1.配置目标对象  -->
                <bean name="userService" class="cn.ith.service.UserServiceImp"></bean>
                <!--2.配置通知对象(目标对象的增强版)-->
                <bean name="myAdvice" class="cn.it_aspect.MyAdvice"></bean>
                <!--3.配置将通知织入目标对象  -->
                <aop:config>
                     配置切入点
                    <aop:pointcut expression="execution(* cn.itheima.service.*ServiceImp.*(..))" id="pc"/>
                    配置切面(切点+通知)
                    <aop:aspect ref="myAdvice">
                        <aop:before method="before" pointcut-ref="pc"/>
                        <aop:after-returning method="afterReturning" pointcut-ref="pc"/>
                        <aop:around method="around" pointcut-ref="pc"/>
                        <aop:after-throwing method="afterException" pointcut-ref="pc"/>
                        <aop:after method="after" pointcut-ref="pc"/>
                    </aop:aspect>
                </aop:config>
            * 测试类代码
                @RunWith(SpringJUnit4Cla***unner.class)
                @ContextConfiguration("classpath:cn/itheima/d_aspect/applicationContext.xml")
                public class Demo {
                    //将名为 userService的目标对象注入到  us成员变量中
                    @Resource(name="userService")
                    private UserService us;
                    @Test
                    public void fun1() {
                        us.save();
                    }
                }
            * 结果对比
            未使用AOP时调用UserService的save方法,结果为 :输出 "保存"字符串
            使用了AOP后,字符串输出结果为:
                前置通知!
                这是环绕通知之前的部分!
                保存
                另一个后置通知(目标方法运行之后调用,无论是否出现异常都会调用)
                这是环绕通知之后的部分!
                后置通知!(如果出现异常则不会调用)

        <4>注解方式 实现AOP的代码示例
            示例需求:对一个UserServiceImpl类 进行AOP增强 其save()方法
             * UserService类(目标对象)
                public interface UserService {void save();}
                public class UserServiceImp implements UserService {
                    @Override
                    public void save() {
                        System.out.println("保存");
                    }
                }
            * MyAdvice(通知对象)
                    //注入切面
                    @Aspect
                    public class MyAdvice {
                        //注入切点
                        @Pointcut("execution(* cn.itheima.service.*ServiceImp.*(..))")
                        //空参方法名pc作为 该切点的id
                        public void pc(){}
                        //注入前置通知,并指定切入点
                        //@Before("execution(* cn.itheima.service.*ServiceImp.*(..))")
                        @Before("MyAdvice.pc()")   //简写
                        public void before() {
                            System.out.println("前置通知!");
                        }
                        //注入后置通知,并指定切入点
                        @AfterReturning("execution(* cn.itheima.service.*ServiceImp.*(..))")
                        public void afterReturning() {
                            System.out.println("后置通知!(如果出现异常则不会调用)");
                        }
                        //注入环绕通知,并指定切入点
                        @Around("execution(* cn.itheima.service.*ServiceImp.*(..))")
                        public Object around(ProceedingJoinPoint pjp) throws Throwable {
                            System.out.println("这是环绕通知之前的部分!");
                            Object proceed = pjp.proceed();  //调用目标方法
                            System.out.println("这是环绕通知之后的部分!");
                            return proceed;
                        }
                        //注入异常拦截通知,并指定切入点
                        @AfterThrowing("execution(* cn.itheima.service.*ServiceImp.*(..))")
                        public void afterException() {
                            System.out.println("出现异常了!");
                        }
                        //注入后置通知,并指定切入点
                        @After("execution(* cn.itheima.service.*ServiceImp.*(..))")
                        public void after() {
                            System.out.println("另一个后置通知(目标方法运行之后调用,无论是否出现异常都会调用)");
                        }
                    }
            * AOP内的配置内容
                <!--1.配置目标对象 -->
                    <bean name="userService" class="cn.itma.service.UserServiceImp"></bean>
                <!--2.配置通知对象 -->
                    <bean name="myAdvice" class="cn.ithnotationAop.MyAdvice"></bean>
                <!-- 开启使用注解完成织入 -->
                    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

原文地址:http://blog.51cto.com/14008076/2314450

时间: 2024-08-02 05:07:42

Spring框架知识复习之二的相关文章

Spring框架知识复习之一

Spring框架复习之一 1 Spring基本介绍 (1)Spring概述: <1>Spring是一个分层的javaSE/EE full-stack(一站式) 轻量级开源框架. <2>Spring的核心是控制反转(IOC)和面向切面(AOP), <3>IOC和DI: * IOC(Inversion Of Control)控制反转:将对象的创建权交给spring,提高解耦合性 * DI(Dependency Injection 依赖注入): 在IOC的环境下,spring

Spring框架学习之IOC(二)

Spring框架学习之IOC(二) 接着昨天的内容,下面开始IOC基于注解装配相关的内容 在 classpath 中扫描组件 <context:component-scan> 特定组件包括: –@Component: 基本注解, 标识了一个受 Spring 管理的组件 –@Respository: 标识持久层组件 –@Service: 标识服务层(业务层)组件 –@Controller: 标识表现层组件 对于扫描到的组件, Spring 有默认的命名策略: 使用非限定类名, 第一个字母小写.

spring框架学习笔记(二)

配置Bean Ioc容器 Ioc容器需要实例化以后才可以从Ioc容器里获取bean实例并使用. spring提供两种方式类型的Ioc容器实现: BeanFactory:底层的,面向spring框架的. ApplicationContext :面向开发人员的,一般用这个. 有两个实现类: ClassPathXmlApplicationContext:从类路径下加载配置文件. FileSystemXmlApplicationContext:从文件系统中加载配置文件. 两种方式配置文件是相同的. 通过

Spring零碎知识复习

自学了Spring也有一段时间了,多多少少掌握了一些Spring的知识,现在手上也没有很多的项目练手,就将就着把这些学到的东西先收集起来,方便日后用到的时候没地方找. 1.spring的国际化 主要是配置文件: 1 <bean id="messageSource" 2 class="org.springframework.context.support.ResourceBundleMessageSource"> 3 4 <!-- 传入资源文件 --

Spring框架知识总结-注入Bean的各类异常

近日整合sping和hibernate框架时遇到了一系列的异常,本次主要说明一下spring框架可能出现的异常及解决方案. 我们借助sping强大的bean容器管理机制,通过BeanFactory轻松的实现javabean的生命周期管理,然而在配置管理的时候难免会遇到一些异常: 异常1:No qualifying bean of type […] found for dependency 例如将BeanB自动注入到BeanA @Componentpublic class BeanA { @Aut

Java知识复习(二)

如何格式化日期? SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); Date dat=new Date(); //把日期转化为字符串 String str=sdf.format(dat); System.out.println(str); //将字符串转化为日期 Java.util.Date d1=sdf.parse("yyyy-mm-dd"); String s = new Stri

Spring 框架学些(二)Spring AOP

关于AOP AOP,面向切面编程是OOP之后出现的概念(大概). 面向对象基本上就是针对类来设计代码,类中定义方法,逻辑中调用不同的类中不同的方法构成业务. 切面 而面向切面中的切面到底是什么.在业务逻辑中,我们会分很多不同的模块,也有不同的类,而这些类的一些方法中,有一些共性功能.比如认证.日志.限流等功能,在各个模块都需要,那每一个功能可以被认为是一个切面. 类似一个三明治,面包.火腿.菜叶.番茄等等每一层都是一个功能模块,一刀切下去这个切面贯穿整个三明治各层,这一刀就形成一个切面,而这个切

C# 基础知识复习(二)------internal 封装

C# 封装 封装 被定义为"把一个或多个项目封闭在一个物理的或者逻辑的包中".在面向对象程序设计方法论中,封装是为了防止对实现细节的访问. 抽象和封装是面向对象程序设计的相关特性.抽象允许相关信息可视化,封装则使开发者实现所需级别的抽象. C# 封装根据具体的需要,设置使用者的访问权限,并通过 访问修饰符 来实现. 一个 访问修饰符 定义了一个类成员的范围和可见性.C# 支持的访问修饰符如下所示: Public:所有对象都可以访问: Private:对象本身在对象内部可以访问: Pro

基础知识复习(二)——stdafx.h 头文件及x&amp;(x-1)运算

今天好久没写过C++程序了,使用VS2013 新建空的控制台程序,结果自动生成了头文件和main 方法. 就了解了stdafx.h头文件的含义及用法. stdafx:standard Application Framework  extended,是预编译文件,将工程中的使用的一些标准的MFC 头文件预先编译,该工程再次编译时,就不需要编译该头文件,可直接使用编译的结果,可加快编译速度,节省程序运行时间. x&(x-1),可将X中最后一位1 置为0: 使用x&(x-1)有两种用法:1,求x