spring容器的使用

1、IOC和DI

IOC: 控制反转

即控制权的转移,将我们创建对象的方式反转了,以前对象的创建是由我们开发人员自己维护,包括依赖关系也是自己注入。使用了spring之后,对象的创建以及依赖关系可以由spring完成创建以及注入,反转控制就是反转了对象的创建方式,从我们自己创建反转给了程序创建(spring)

DI: Dependency Injection 依赖注入

spring这个容器中,替你管理着一系列的类,前提是你需要将这些类交给spring容器进行管理,然后在你需要的时候,不是自己去定义,而是直接向spring容器索取,当spring容器知道你的需求之后,就会去它所管理的组件中进行查找,然后直接给你所需要的组件. 实现IOC思想需要DI做支持 注入方式: 1.set方式注入 2.构造方法注入 3.字段注入 注入类型: 1.值类型注入 2.引用类型注入

好处:

1.降低组件之间的耦合度,实现软件各层之间的解耦.


2.可以使容器提供众多服务如事务管理消息服务处理等等。当我们使用容器管理事务时,开发人员就不需要手工 控制事务,也不需要处理复杂的事务传播


3.容器提供单例模式支持,开发人员不需要自己编写实现代码.


4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能


5.容器提供众多的辅佐类,使这些类可以加快应用的开发.如 jdbc Template Hibernate Template

•Spring 容器是 Spring 框架的核心。容器负责管理Bean对象。

•容器的两种实现:

•BeanFactory 容器:最简单的容器,给 DI 提供了基本的支持。 •ApplicationContext 容器,继承的BeanFactory,拥有更丰富的功能。

、国际化支持、资源访问、事件发布、载入多个配置文件

•容器提供的常用方法: •getBean():获取容器的中指定的bean对象。 •containsBean():判断容器中是否存在指定的bean对象。 •isPrototype():判断指定的bean是否为非单例对象。 •isSingleton():判断指定的bean是否为单例对象。

ApplicationContext

•Spring容器中的顶层接口是BeanFactory。ApplicationContext是它的 子接口(注意这个也是个接口哦)。 •ApplicationContext的三个主要的实现类: •ClassPathXmlApplication:它是从类的根路径下加载xml配置文件(推荐用这种)。 •FileSystemXmlApplication: 它是从磁盘路径上加载配置文件,配置文件可以在磁 盘的任意位置。(但使用不灵活,不推荐) •AnnotationConfigApplication:当我们使用注解配置容器对象时,需要使用此类来 创建spring容器。它用来读取注解。(Springboot默认使用这个)

•在早期的Spring框架中都是采用XML的方式来装配Bean •创建一个xml文件application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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.xsd">
</beans>

•使用bean标签来装备Bean对象

 <bean id="user" class="com.project.bean2.User">
</bean>

•通过容器来构造Bean对象

ClassPathXmlApplicationContext ctx = new  ClassPathXmlApplicationContext("application.xml");
// 通过名字来获取Bean对象
User user = (User)ctx.getBean("user");
// 通过类型来获取Bean对象
User user1 = ctx.getBean(User.class);

Bean的作用域

•默认情况下,Spring只为每个在IOC容器里声明的Bean创建唯一一个实例, 整个IOC容器的范围内都能共享该实例,即单例模式。 •在xml配置的bean标签上通过scope属性来设置作用域。

类别说明
singleton在SpringIOC容器中仅存在一个Bean实例,Bean以单实例的方式存在 , 默认是singleton; scope="singleton";
prototype每次调用getBean()时都会返回一个新的实例 ,在<bean>标签中加上scope="prototype";
request每次Http请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session同一个Http Session共享一个Bean,不同的Http Session使用不同的Bean。该作用域仅适用于WebApplicationContext环境

依赖注入方式

Bean对象中的属性值通过IOC容器进行注入,这种方式称为依赖注入。

依赖注入的方式有三种:

属性注入

属性注入的本质就是通过setter方法注入。 在xml中通过使用property标签来注入,其中name属性是对象中的属性名,value是属性值。

    <bean id="carTyle" class="com.project.bean2.CarTyle" scope="prototype">
        scope="prototype"每次调用getBean()时都会返回一个新的实例
        <!--属性注入是通过set方法进行注入,此时会用到property标签 ,name是属性名称   value是属性值  -->
        <property name="size" value="100"></property>
    </bean>
​
​
    <bean id="user" class="com.project.bean2.UserBean">
        <!--      属性注入的本质是用set方法,所以  需要无参构造-->
        <property name="id" value="100"></property>
        <property name="name" value="戈尔巴&lt;乔夫"></property>
        <property name="address" value="莫斯科"></property>
        <property name="gender" value="男"></property>
        <property name="car" ref="carID"></property>
​
    </bean>

构造器注入

构造方法注入 通过构造方法注入,可以在创建对象时就注入属性值。 在xml中通过使用constructor-arg标签来注入。 在User类中需要创建一个对应的构造方法。(顺序和类型,以及属性数量都要一致)

普通构造器注入
​
<bean id="user" class="com.lovo.bean.User">
    <constructor-arg value="1"></constructor-arg>
    <constructor-arg value="小张"></constructor-arg>
    <constructor-arg value="20"></constructor-arg>
</bean>
​
通过index属性指定参数的顺序
​
<bean id="user" class="com.lovo.bean.User">
    <constructor-arg value="1" index=“0”></constructor-arg>
    <constructor-arg value="小张" “index=“1” ></constructor-arg>
    <constructor-arg value="20" index=“2” ></constructor-arg>
</bean>
                            
 通过类型来匹配参数。
<bean id="user" class="com.lovo.bean.User">
    
    <constructor-arg value="1" type="java.lang.String"></constructor-arg>
​
    <constructor-arg value="20" type="int"></constructor-arg>
    
</bean>   
​
字面值:可以通过value属性或value标签来注入。
若字面值包含特殊字符,可以用<![CDATA[]]>将字面值包裹起来,或者用实体来替换。
<constructor-arg type="java.lang.String">
      <!--   用<![CDATA[]]>将字面值包裹起来  -->
    <value><![CDATA[<chengdu>]]></value>
</constructor-arg>
      <!--用实体字符替换 -->
 <constructor-arg value="戈尔巴&lt;乔夫"></constructor-arg>
      
<constructor-arg type="int">
    <value>20</value>
</constructor-arg>
​
​
引用其他Bean
Bean对象中的属性不仅仅是基本类型或字符串,还有可能是其他Bean对象。
在XML文件中使用ref来引用其他Bean对象。
​
<bean id="address" class="com.lovo.bean.Address">
    <constructor-arg value="红瓦寺" ></constructor-arg>
    <constructor-arg value="四川" ></constructor-arg>
    <constructor-arg value="成都" ></constructor-arg>
</bean>
​
<bean id="user" class="com.lovo.bean.User">
  <property name="address" ref="address"></property>
</bean>

•工厂方法注入(很少使用,不推荐)

4、防止创建多个applicationContext取值/并指定记载spring配置文件的位置——web.xml 1、需要导入包spring-web 2、在web.xml中配置监听器

5、使用注解方式代替配置文件(官方推荐使用注解)

1.在applicationContext.xml中书写指定扫描注解

  2.在类中书写Component

注意:假如不写括号内的值(即name或id),默认使用类名首字母小写作为搜索,为什么意思呢?

比如Student类中使用了@Component 没有书写括号和值,那么默认搜索id或name为student。

 3.指定对象的作用范围Scope
     声明Student类对象为多例       下面是对singleton和prototype的一些补充

singleton作用域:当把一个Bean定义设置为singleton作用域是,Spring IoC容器中只会存在一个共享的Bean实例,并且所有对Bean的请求,只要id与该Bean定义相匹配,则只会返回该Bean的同一实例。值得强调的是singleton作用域是Spring中的缺省作用域。

prototype作用域:prototype作用域的Bean会导致在每次对该Bean请求(将其注入到另一个Bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的Bean实例。根据经验,对有状态的Bean应使用prototype作用域,而对无状态的Bean则应该使用singleton作用域。对于具有prototype作用域的Bean,有一点很重要,即Spring不能对该Bean的整个生命周期负责。具有prototype作用域的Bean创建后交由调用者负责销毁对象回收资源。简单的说:

singleton 只有一个实例,也即是单例模式。

prototype访问一次创建一个实例,相当于new。

4.值类型的注入
                                                                                   实际通过反射field赋值

                                                                                   实际通过set方式赋值

 5.引用类型的注入

面试题: @AutoWired和@Resource的区别?

@AutoWired默认以类型进行查找,@Resource默认以名称进行查找

@AutoWired(required=false) + @Qualifier("user") == @Resource(name="user")

其中@Resource注解是jdk1.6后才有的

6.创建与销毁方法

 7.spring整合junit测试(spring创建容器)
 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration("classpath:applicationContext.xml")    

6、spring中AOP名词解释

JoinPoint(连接点):目标对象中,所有可以增强的方法,就是spring允许你是通知(Advice)的地方,那可就真多了,基本每个方法的前、后(两者都有也行),或抛出异常是时都可以是连接点,spring只支持方法连接点。

Pointcut(切入点):目标对象中,已经被增强的方法。调用这几个方法之前、之后或者抛出异常时干点什么,那么就用切入点来定义这几个方法。

Advice(通知/增强) :增强方法的代码、想要的功能。

Target(目标对象):被代理对象,被通知的对象,被增强的类对象。

Weaving(织入):将通知应用到连接点形成切入点的过程

Proxy(代理):将通知织入到目标对象之后形成的代理对象

aspect(切面):切入点+通知————通知(Advice)说明了干什么的内容(即方法体代码)和什么时候干(什么时候通过方法名中的before,after,around等就能知道),二切入点说明了在哪干(指定到底是哪个方法),切点表达式等定义。

虽然现在都用Maven项目构建,但是不能忘记,使用aop需要用到的包:spring-aop + spring-aspects + springsource.org.aopalliance + springsource.org.aspectj.weaver

关于AOP看一个小例子:

1、准备目标对象(被代理对象,被通知的对象,被增强的类对象)

  2、准备通知(被增强方法的代码,想要实现功能的方法代码)

   3、配置 applicationContext.xml
        1.导入aop(约束)命名空间
        2.配置目标对象
        3.配置通知对象
        4.配置将通知织入目标对象

    4、测试

总结:通知的几种类型 1.前置通知———目标方法运行之前调用 2.后置通知———目标方法运行之后调用(如果出现异常不调用) 3.环绕通知———目标方法之前和之后都调用 4.异常拦截通知———如果出现异常,就会调用 5.后置通知———目标方法运行之后调用(无论是否出现异常都会调用)

 7、spring中的aop使用注解配置
   1、applicationContext.xml中配置目标对象,通知对象,开启使用注解完成织入

 2、@Aspect注解代表该类是个通知类,书写切点表达式@Pointcut("execution(返回值 全类名.方法名(参数))")

注意环绕通知需要这么写:

public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { //环绕方法执行前 //proceedingJoinPoint.proceed();表示对拦截的方法进行放行 //若注释proceedingJoinPoint.proceed()则不会执行被AOP匹配的方法 proceedingJoinPoint.proceed(); //环绕方法执行后 } AOP注解解析:

@Before 前置通知(Before advice) :在某连接点(JoinPoint)——核心代码(类或者方法)之前执行的通知,但这个通知不能阻止连接点前的执行。为啥不能阻止线程进入核心代码呢?因为@Before注解的方法入参不能传ProceedingJoinPoint,而只能传入JoinPoint。要知道从aop走到核心代码就是通过调用ProceedingJionPoint的proceed()方法。而JoinPoint没有这个方法。 这里牵扯区别这两个类:Proceedingjoinpoint 继承了 JoinPoint 。是在JoinPoint的基础上暴露出 proceed 这个方法。proceed很重要,这个是aop代理链执行的方法。暴露出这个方法,就能支持 aop:around 这种切面(而其他的几种切面只需要用到JoinPoint,这跟切面类型有关), 能决定是否走代理链还是走自己拦截的其他逻辑。建议看一下 JdkDynamicAopProxy的invoke方法,了解一下代理链的执行原理。这样你就能明白 proceed方法的重要性。

@After 后通知(After advice) :当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。

@AfterReturning 返回后通知(After return advice) :在某连接点正常完成后执行的通知,不包括抛出异常的情况。

@Around 环绕通知(Around advice) :包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。这时aop的最重要的,最常用的注解。用这个注解的方法入参传的是ProceedingJionPoint pjp,可以决定当前线程能否进入核心方法中——通过调用pjp.proceed();

@AfterThrowing 抛出异常后通知(After throwing advice) : 在方法抛出异常退出时执行的通知。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值