spring的bean管理(注解)

注解介绍

1 代码里面特殊标记,使用注解可以完成功能

2 注解写法@注解名称(属性名称=属性值)

3 注解使用在类上面,方法上面 和 属性上面

自动装配Bean

spring IoC容器可以自动装配(autowire)相互协作bean之间的关联关系。因此,如果可能的话,可以自动让Spring通过检查BeanFactory中的内容,来替我们指定bean的协作者(其他被依赖的bean)。

简而言之,就是对于bean当中引用的其他bean不需要我们自己去配置它该使用哪个类,Spring 的自动装配可以帮助我们完成这些工作。

autowire 的值有5个:default, no, byName, byType, constructor其中default等价于no

自动装配优点:

l 自动装配能显著减少配置的数量。

l 自动装配可以使配置与Java代码同步更新。

在开发过程中推荐采用自动装配,而在系统趋于稳定的时候改为显式装配的方式。

自动装配有5中类型:

byName

根据属性名自动装配。此选项将检查容器并根据id的名字查找与属性名完全一致的bean,并将其与属性自动装配

byType

如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配;如果存在多个该类型bean,那么抛出异常,并指出不能使用byType方式进行自动装配;

如果没有找到相匹配的bean,则什么事都不发生,属性也不会被设置

constructor

与byType的方式类似,不同之处在于它应用于构造器参数。

如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常

autodetect

通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式。高版本已经弃用

no

默认 。 必须显示的使用"<ref />"标签明确地指定bean合作者,对于部署给予更大的控制和明了


spring注解开发准备

1 导入jar包(可通过maven管理)

1)导入基本的jar

 Spring框架入门篇(二)

2)导入aopjar

 Spring框架入门篇(二)

2 创建类,创建方法


3 创建spring配置文件,引入约束

1)第一篇做ioc基本功能,引入约束beans

2)做springioc注解开发,引入新的约束

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

4 开启注解扫描

<!--第一步  开启注解扫描-->
<context:annotation-config />
<!--第二步  设置需要扫描的包-->
<context:component-scan base-package="com.keduox1"/>

注解创建对象

1.在创建对象上面使用注解
@Repository(value = "userDao")
public class UserDao {
    public void add(){
        System.err.println("成功使用了user对象");
    }
}
2.创建对象有四个注解

1@Component

2@Controller

3@Service

4@Repository

目前这四个注解功能是一样的,都创建对象。只是针对于java三层模式,便于理解。


3.创建对象是单实例还是多实例
@Component(value = "user")
/*@Scope(value = "prototype")每一次都会创建一个新的对象*/
@Scope(value = "prototype")
public class User implements Serializable {

注解注入属性

@Component(value = "userservice")
public class UserService {
    //@Autowired是根据类型注入数据,与@Repository的value的值无关
// @Autowired

    //根据名称(id)注入数据
    //如果@Repository没有value值,
    //那么@Resource自动指定的值是UserDao的类名的首字母小写的值
    @Resource(name="userDao")
    private UserDao userDao;
}

配置文件和注解混合使用

1 创建对象操作使用配置文件方式实现

2 注入属性的操作使用注解方式实现

<!-- 开启注解扫描 
   (1)到包里面扫描类、方法、属性上面是否有注解
-->
<context:component-scan base-package="cn.itcast"></context:component-scan>

<!-- 配置对象 -->
<bean id="bookService" class="cn.itcast.xmlanno.BookService"></bean>
<bean id="bookDao" class="cn.itcast.xmlanno.BookDao"></bean>
<bean id="ordersDao" class="cn.itcast.xmlanno.OrdersDao"></bean>
Bean的生命周期


spring Framework支持五种作用域(其中有三种只能用在基于web的Spring ApplicationContext)。内置支持的作用域分列如下:

singleton

在每个Spring IoC容器中一个bean定义对应一个对象实例。

prototype

一个bean定义对应多个对象实例。

request(了解)

在一次HTTP请求中,一个bean定义对应一个实例;即每次HTTP请求将会有各自的bean实例, 它们依据某个bean定义创建而成。该作用域仅在基于webSpring 开发情形下有效。

session(了解)

在一个HTTP Session 中,一个bean定义对应一个实例。该作用域仅在基于webSpring开发情形下有效。

global session(了解)

在一个全局的HTTP Session 中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于webSpring ApplicationContext 情形下有效。

生命周期: 构造器、init方法、获取bean后的操作、destroy方法(ctx.close时执行).

注意:如果beanscope设为prototype时,当ctx.close时,destroy方法不会被调用.

原因:对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责:容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法。但对prototype而言,任何配置好的析构生命周期回调方法都将不会 被调用。清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责。(让Spring容器释放被prototype作用域bean占用资源的一种可行方式是,通过使用bean的后置处理器,该处理器持有要被清除的bean的引用。)谈及prototype作用域的bean时,在某些方面你可以将Spring容器的角色看作是Java new 操作的替代者。任何迟于该时间点的生命周期事宜都得交由客户端来处理。

Spring框架入门篇(二)1. 生命周期图

Spring框架入门篇(二)
2. 生命周期顺序

(一).Bean的建立

BeanFactory读取Bean定义文件,并生成各个实例

(二).属性注入

执行相关的Bean属性依赖注入

(三).BeanNameAwaresetBeanName()

如果Bean实现BeanNameAwar接口,则执行setBeanName()

(四).BeanFactoryAwaresetBeanFactory()

如果Bean实现BeanFactoryAware接口,则执行setBeanFactory()

(五).ApplicationContextAware接口

setApplicationContext()方法

(六).BeanPostProcessorsprocessBeforeInitialization()

如果有任何BeanPostProcessors实例与Bean实例关联,则执行BeanPostProcessors实例processBeforeInitialization()

(七).InitializingBeanafterPropertiesSet()

如果Bean有实现InitializingBean,则执行afterPropertiesSet()

(八).Bean定义文件中定义init-method

<bean id="…" class="…" init-method="initBean">

(九).BeanPostProcessorsprocessaAfterInitialization()

如果有任何的BeanPostProcessors实例与Bean实例关联,则执行BeanPostProcessors实例的processaAfterInitialization()

(十).DisposableBeandestroy()

在容器关闭时,如果Bean类实现DisposableBean接口,则执行destroy()

(十一).Bean定义文件中定义destroy-method

<bean id="…" class="…"destroy-method="destroyBean">


3.各种接口方法分类

Bean的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

1Bean自身的方法  :  这个包括了Bean本身调用的方法和通过配置文件中<bean>init-methoddestroy-method指定的方法

2Bean级生命周期接口方法  :  这个包括了BeanNameAwareBeanFactoryAwareInitializingBeanDiposableBean这些接口的方法

3、容器级生命周期接口方法  :  这个包括了InstantiationAwareBeanPostProcessorBeanPostProcessor这两个接口实现,一般称它们的实现类为后处理器

4、工厂后处理器接口方法  :  这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器  接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

详细生命周期:http://www.cnblogs.com/zrtqsk/p/3735273.html

Aop面向切面编程

1 aop:面向切面(方面)编程,扩展功能不修改源代码实现

 

2 AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码

 

3 aop底层使用动态代理实现

1)第一种情况,有接口情况,使用动态代理创建接口实现类代理对象

2)第二种情况,没有接口情况,使用动态代理创建类的子类代理对象


aop核心概念

软件系统,可看作由一组关注点组成。其中,直接的业务关注点,是核心关注点。而为核心关注点提供服务的,就是横切关注点。而封装各种横切关注点的类,就是切面。

横切关注点与切面之间:横切关注点是切面中封装的各种方法。即横切关注点是各种服务性方法,切面是封装各种横切关注点的类。就是类与方法的关系。

备注:业务处理的主要流程是核心关注点,扩展(增强)核心关注点的部分是横切关注点

1、横切关注点

软件系统,可看作由一组关注点组成。其中,直接的业务关注点,是核心关注点。而为核心关注点提供服务的,就是横切关注点。一般情况下,切面中封装的方法都是横切关注点。

2、切面(aspect)

封装各种横切关注点的类,就是切面

3、连接点(joinpoint)

所谓连接点是指那些被拦截到的点。就是spring配置文件中的切入点表达式中需要拦截的所有的方法

4、切入点(pointcut)

所谓切入点是指我们要对那些joinpoint进行拦截的定义

在类里面可以有很多方法被增强,比如实际操作中,需要增强类里面的add方法和update方法,那么当前被增强的方法称为切入点

5、通知(advice)

所谓通知是指拦截到joinpoint之后所要做的事情(增强的代码)就是通知通知分为前置通知后置通知异常通知最终通知环绕通知

前置通知:在方法执行前执行

后置通知:在方法执行后执行

异常通知:在执行核心关注点过程中,如果抛出异常则会执行

返回通知:在后置之前执行(如果出现异常,不执行)--在方法正常执行通过之后执行的通知

环绕通知在方法之前和之后执行

6、目标对象(Target

代理的目标对象,即增强方法所在的类

7、织入(weave)

将切面应用到目标对象并导致代理对象创建的过程

或者说把增强用到类的过程

8、引入(introduction)

一般不适用

在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

Spring的aop操作

1 在spring里面进行aop操作,使用aspectj实现

1aspectj不是spring一部分,和spring一起使用进行aop操作

2Spring2.0以后新增了对AspectJ支持

2 使用aspectj实现aop有两种方式

1)基于aspectjxml配置

2)基于aspectj的注解方式

aop编程准备

1 除了导入基本的jar包之外,还需要导入aop相关的jar

Spring框架入门篇(二) 

2 创建spring核心配置文件,导入aop的约束

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
3.使用表达式配置切入点

常用表达式:

下面方法中的..表示:可以包含参数

 execution(* com.yunlian.service.UserService.add(..))

 execution(* com.yunlian.service.UserService.*(..))—某个类的所有方法

 execution(* com.yunlian.service.*.*(..))---service包下面的所有类的所有方法

 execution(* *.*(..))---所有类中的所有方法

注解方式实现

第一步:创建需要增强的类

public class Book {

   public void add() {
      System.out.println("add...........");
   }
}

第二步:创建增强的类

/**
 * aop切面编程。 增强Book类
 */
public class MyBook {

   public void before1() {
      System.out.println("前置增强......");
   }
   
   public void after1() {
      System.out.println("后置增强......");
   }
   
   //环绕通知
   public void around1(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
      //方法之前
      System.out.println("方法之前.....");
      
      //执行被增强的方法
      proceedingJoinPoint.proceed();
      
      //方法之后
      System.out.println("方法之后.....");
   }
}

第三步:配置文件

<!-- 1  配置对象 -->
<bean id="book" class="cn.itcast.aop.Book"></bean>
<bean id="myBook" class="cn.itcast.aop.MyBook"></bean>

<!-- 2 配置aop操作 -->
<aop:config>
   <!-- 2.1 配置切入点 连接点  -->
   <aop:pointcut expression="execution(* cn.itcast.aop.Book.*(..))" id="pointcut1"/>
   
   <!-- 2.2 配置切面   把增强用到方法上面-->
   <aop:aspect ref="myBook">
      <!-- 配置增强类型 
         method: 增强类里面使用哪个方法作为前置
      -->
      <aop:before method="before1" pointcut-ref="pointcut1"/>
      
      <aop:after-returning method="after1" pointcut-ref="pointcut1"/>
      
      <aop:around method="around1" pointcut-ref="pointcut1"/>
   </aop:aspect>
</aop:config>

相关文章:

  • 2021-07-29
  • 2021-10-24
  • 2021-08-14
  • 2022-01-05
  • 2021-05-03
  • 2022-01-01
  • 2022-01-09
猜你喜欢
  • 2021-05-16
  • 2021-06-08
  • 2021-11-23
  • 2021-11-18
  • 2021-11-27
  • 2021-07-07
相关资源
相似解决方案