spring是一个开源的控制反转(IOC)和面向切面(AOP)的容器框架,主要目的就是简化企业开发

spring的依赖注入:在程序运行期间,由外部容器动态的将依赖对象注入到组件中

实例化spring容器的二种方法
第一种:在类路径下寻找配置文件来实例化容器(实际开发中使用此方法
ApplicationContext ctx= new ClassPathXmlApplicationContext(new String [] {"beans.xml"})
spring的配置文件可以有多个,所有可以用一个string数组来接收
第二种:在文件路径下寻找配置文件来实例化容器
ApplicationContext ctx= new FileSystemApplicationContext(new String [] {"bean.xml"})
spring获取bean
ApplicationContext ctx= new ClassPathXmlApplicationContext("beans.xml")
PersonService(接口) personService=( PersonService) ctx.getBean(personService);
spring中三种实例化bean的方法

第一种:构造器实例化bean( 基本上都用它,下边二种了解
<bean id="personService" class="com.jary.service.impl.PersonServiceBean"/>
第二种:静态工厂实例化bean
<bean id="orderService" class="com.jary.service.OrderFactory factory-method="createOrder"/>
public class OrderFactory{
   public static OrderServiceBean createOrder(){
        return new OrderServiceBean();
}
}

第三种:实例工厂方法实例化bean
<bean id="orderFactory" class="com.jary.service.OrderFactory "/>
<bean id="orderService"  factory-bean="personServicefactory-method="createOrder"/>
public class OrderFactory{
   public OrderServiceBean createOrder(){
        return new OrderServiceBean();
}
spring中bean的作用域 
通过scope来设置作用域范围
默认作用域singleton( 每次从spring容器中取出同一个对象)
<bean id="personService" class="com.jary.service.impl.PersonServiceBean " scope="singleton"/>
singleton作用域:当spring ioc容器中一个bean只有一个实例对象,默认情况下初始化容器时,就初始化bean
但是我们可以指定bean节点的lazy-init=ture来延时初始化bean
<bean id="personService" class="com.jary.service.impl.PersonServiceBean " lazy-init="true"/>
指定作用域:prototype( 每次从spring容器中取出新的对象)
<bean id="personService" class="com.jary.service.impl.PersonServiceBean " scope="prototype"/>

spring的依赖注入三种方式

第一种:构造器注入(最常用)
第二种:使用属性的setter方法注入
第三种:使用Field注入(采用注解方式)
注入依赖通常采用手工装配和自动装配,建议采用手工装配方式,因为自动装配可能会产生无法预见的结果
spring的依赖注入装配 引用类型 二种方法

在配置文件beans.xml配置bean
第一种:注入其他bean,使用ref来指定那个bean(实际开发中,使用此方法)

把要注入对象personDao( 基于接口实现的bean)注入personService( 基于接口实现的bean)中
  
<bean id=" personDao1" class="com.jary.service.impl.PersonDaoBean" >
<bean id="personService" class="com.jary.service.impl.PersonServiceBean" />
      <property name="personDao" ref="personDao1"></property>
</bean>
第二种:使用内部bean,但该bean不能被其他bean使用
把要注入对象personDao( 基于接口实现的bean)注入personService( 基于接口实现的bean)属性内部

<bean id="personService" class="com.jary.service.impl.PersonServiceBean" />
      <property name="personDao">
     <bean class="com.jary.service.impl.PersonDaoBean" >
     </property>
</bean>
           

 spring的依赖注入装配基本类型方法

<bean id="personDao1" class="com.jary.service.impl.PersonDaoBean" >
<bean id="personService" class="com.jary.service.impl.PersonServiceBean" />
<construtor-arg index="0" type="java.lang.string" value="xxx" /> //构造器参数注入,index表示构造器参数第几个,type表示参数的类型  value表示基本类型
<construtor-arg index="0" type="java.lang.string" ref=" personDao1" /> //构造器参数注入,index表示构造器参数第几个,type表示参数的类型,ref表示引用类型
  <property name="name"  value="j aryle " /> //属性setter注入
spring的依赖注入装配集合类型的方法 set集合的注入 Set set= new HashSet();
<bean id="personService" class="com.jary.service.impl.PersonServiceBean" />
 <property name="sets"  >
       <set>   
            <value> 第一个</value>
             <value> 第二个</value>
            <value>  第三个</value>
     </set>
</property>
 
List集合的方式 List list = new ArraryList();
 
<bean id="personService" class="com.jary.service.impl.PersonServiceBean" />
 <property name="lists"  >
       <list>   
            <value> 第一个</value>
             <value> 第二个</value>
            <value>  第三个</value>
     </list>
</property>
 
Map集合的方式Map map=new HashMap();
  
<bean id="personService" class="com.jary.service.impl.PersonServiceBean" />
 <property name="maps"  >
       <map>   
            <entry key="key1" value="value1" /> 
              <entry key="key2" value="value2" />
             <entry key="key3" value="value3" />
     </map>
</property>
 spring依赖注入采用注解的方式手工装配bean对象(使用前提是标注在字段和setter方法上
      需要在spring配置文件beans.xml加入注解的一些约束文件和配置注解的打开
   <context:annocation-config /> //配置注解的打开
   @Autowired和@Resource注解进行装配,二者的区别是@Autowired默认按类型装配,@Resource默认是按照名称装配,当找不到与名称匹配的bean就会按照类型装配。
   注意:建议使用@Resource进行装配,它是javaee中的包,而@Autowired是spring提供的注解包,扩展性没有前者好
    @Autowired默认情况下要求依赖对象必须存在,如果允许null值,可以设置它的required属性为false,如果想使用按照名称装配,可以结合@Qualifier注解一起使用,如下:
    @Autowired @Qualifier("personDaoBean")
    private PersonDao personDao;
    @Resource注解和@Autowired一样,亦可以标注在字段和setter方法上,但是它默认按照名称装配,名称可以通过它的name属性来指定,
    
  spring的自动装配,了解就行,不建议使用(会出现不可预知的结果)

spring容器自动扫描和管理bean(掌握)
  通过在classpath自动扫描方式把组件纳入spring容器中管理
   使用自动扫描的重要性:如果我们都是有xml的bean定义来配置组件,在一个稍大的项目中,通常会有上百个组件
   显然会增加配置文件的体积,查找和维护起来不太方便,所以才引入在类路径下寻找标注了@Component(泛指组件,当组件不好归类时,使用此组件)、@Service(标注业务层相当于mvc中model)、    @Controller(标注控制层组件相当于struts2中action)、@Repository(标注数据访问组件即dao组件)注解的类,并把它们纳入spring容器中管理,我们只需要在beans.xml配置中打开自动扫描<context:component-scan base-package="cn.itcast" />
实例代码:
   @Service("personService"(可以自定义名称,默认是类名PersonServideBean)) @scope("prototype"(作用域范围))
   public class PersonServiceBean implements PersonService{
}
  还有二个注解可以起到在,<bean init-method=""   destory-method="" />
 
一个是bean被实例化之前执行初始化某个方法@PostConstruct(相当于init-method)
例如:@PostConstruct
          public  void init(){
          System.out.println("初始化");
}
 另外一个是在bean销毁之前执行的注解@PreDestory(相当于destory-method)

spring AOP技术(Proxy代理对象)(权限控制使用最多)(掌握)
   
具体实现:拦截所有的业务方法
                 判断是否有权限,有则通过,否则反之

 动态代理Proxy是创建的代理对象依赖于目标对象实现了接口来实现的。如果目标对象没有接口实现spring提供了第三方框架CGlib
 动态代理创建代理工厂,有代理工厂生成代理对象,
 创建代理工厂 代码片段如下:
  public class ProxyFactory implements InvocationHandler{
    private Object targetObject;//目标对象
    public Object createProxyIntance(Object targetObject){
      this.targetObject=targetObject;
     Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),this.targetObject.getClass().getInterfaces(),this);
    //由于实现了InvocationHandler接口,就实现它所有方法
     public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
          
          Object result=method.invoke(targetObject,args);
         
}
}

}

spring中的AOP面向切面编程(重点掌握)
首先了解一下AOP中的概念
Aspect(切面):横切性关注点的抽象即为切面,它与类相似,只是二者的关注点不一样,类是对物体特征的抽象,而切面是横切性关注点的抽象
joinpoint(连接点):那些被拦截到的点,在spring中这些点指的是方法,因为spring只支持方法类型的连接点,实际上,joinpoint还可以是field和类构造器
Pointcut(切入点):对那些joinpoint进行拦截的定义
Advice(通知):拦截到joinpoint之后所要做的事情就是通知,通知分为前置通知,后置通知,异常通知,最终通知,环绕通知。
Target(目标对象):代理的目标对象
Weave(织入):指将aspect应用到target对象并导致proxy对象创建的过程即是织入。
Introduction(引入):在不修改类代码的前提下,Introduction可以在运行期为类动态的添加一些方法和field。

利用spring来实现AOP切面编程


还要在spring配置文件beans.xml中<aop:aspectj-autoproxy />


基于注解方式声明切面

@Aspect
   public class Logprint{
   @Pointcut("execution(* com.jary.service..*.*(..))");//对com.jary.service包下面的子包以及子包下面的所以方法进行拦截
      private void anyMethod(){}//声明一个切入点
      @Before("anyMethod")//定义前置通知,在拦截方法执行前执行
      public void doAccessCheck(){ System.out.println("前置通知")}
      @AfterReturning("anyMethod")//通知都是基于一个切入点定义的方法(anyMethod)展开的
      public void doAfterReturning(){ System.out.println("后置通知")}//在拦截方法执行后执行
      @After("anyMethod")
      public void doAfter(){System.out.println("最终通知")} //在后置通知之后执行
      @AfterThrowing("anyMethod")//异常通知,发生异常的时候才会执行
      public void doAfterThrowing(){System.out.println("异常通知")}//上图可以看出当异常通知执行时,后置通知将不会被执行,前置通知,最终通知还是会执行
      @Around("anyMethod")//环绕通知可以实现上面的所有通知
      public Object doBasicProfiling( ProceedingJoinPoint pjp) throw Throwable{ 
      //环绕通知对于权限的设定首选
      //if(){//判定用户是否有权限
      System.out.println("进入方法");
      Object result=pjp.proceed();//固定格式,必须执行此方法
      System.out.println("退出方法");
      return result; 
}
}

上图中在前置通知中获取方法的参数,在后置通知中获取有返回值的方法的返回值

基于XML配置文件来进行AOP编程



我们可以根据拦截切入点表达式来拦截特定的业务方法,例如:

上面的表达式只能拦截业务方法参数为string类型的方法

上面的表达式只能拦截业务方法没有返回值的方法

spring的事物管理(重点掌握)
     基于注解开发的事务管理(掌握,项目中大多使用注解方式管理事务,可以精确定位到业务方法上,比较灵活),在配置文件中加入如下图所示:注解方式开启事务管理器
     
     

      如果想把事物交给spring管理,就在业务bean类上加入@Transactional来实现
      默认情况下,spring管理事务时,当业务方法抛出运行期异常RuntimeException(也叫unchecked)是回滚事务的,如下图:
      

     但是当业务方法抛出Exception异常时(checked),不回滚事物,如下图:
      
      我们也可手工配置强制方法抛出Exception异常时(checked),回滚事物的实现方法
      在业务方法上加入@Transational(rollbackFor=Exception.class)

如下图
      
     同理我们也可以使用手动强制方法抛出RuntimeException运行期例外不回滚事物,实现方法
     在业务方法上@Transational(norollbackFor=RuntimeException.class),如下图所示:
     
     spring容器中有些业务方法不需要开启事物,例如查询方法,可以使用事务的传播行为(propagation属性)来实现,
      @Transational(propagation=Propagation.NOT_SUPPORTED)
     如下图所示:
      
       事物的传播属性有以下几种,默认事物传播属性是:REQUIRED
        
      spring容器中的业务方法开启事务,当事务并发时,要设置事物的隔离级别  @Transational(isolation事物的隔离级别属性=repeatable read),这个级别和数据库系统有关,和spring容器无关,mysql数据库默认隔离级别为repeatalbe read(可重复读),级别蛮高的
       
       基于xml配置文件管理事务(掌握),id=txManager的bean是事务管理器,这里利用AOP来拦截一些符合要事物管理的业务方法,然后通过通知<tx:advice id="txAdvice" transation-manager="txManager" >来为我们的业务bean配置业务方法的行为<tx:method name="get.*" read-only="true" propagation="NOT_SUPPORTED" />(配置业务方法为get开头的事务为只读,并且不开启事务)
<tx:name="*" />(配置其他业务方法为默认的事务传播行为REQUIRED)
       
       
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐