Spring增强

  • 1. 依赖注入;(掌握)
  • 2. XML自动注入;(掌握)
  • 3. 全注解配置;(掌握)
  • 4. 代理模式;(掌握,难点)

依赖注入

 构造参数注入

 

constructor-arg:构造器注入: index:顺序   name:行参的名称   type:类型    ref:关联另一个bean     id关联;

 

              内部定义一个bean      value:值(普通属性的值-String,Integer,Long,...

 

方案一:根据构造器参数的顺序(索引)

 

<!-- 按照索引注入,索引开始为0 -->

扫描二维码关注公众号,回复: 5486229 查看本文章

 

<bean id="MyBean" class="cn.itsource._01_.MyBean">

 

<constructor-arg index="0" value="666" />

 

<constructor-arg index="1" value="张二娃" />

 

</bean>

      方案二:根据构造器参数的名称

 

<!-- 按照名称注入,名称必须一致 -->

 

<bean id="MyBean" class="cn.itsource._01_.MyBean">

 

<constructor-arg name="id" value="1" />

 

<constructor-arg name="name" value="张三娃" />

 

</bean>

方案三:根据构造器的类型注入

 

<!-- 按照类型注入,必须一一对应,不能有重复的类型-->

 

<bean id="MyBean" class="cn.itsource._01_.MyBean">

 

<constructor-arg type="java.lang.Long" value="1" />

 

<constructor-arg type="java.lang.String" value="张四娃" />

 

</bean>

 

 

 

 

 

如果有一个参数是我们自己的一个对象,怎么解决?

 

方案一:先在外面定义好

<bean id="otherBean" class="cn.itsource._01_.OtherBean"/>

<bean id="MyBean" class="cn.itsource._01_.MyBean">

<constructor-arg  value="1" />

<constructor-arg  value="张五娃" />

<constructor-arg ref="otherBean"/>

</bean>

方案二: 使用一个内部的Bean完成(不需要加id)

 

<bean id="MyBean" class="cn.itsource._01_.MyBean">

 

<constructor-arg  value="1" />

 

<constructor-arg  value="张六娃" />

 

<constructor-arg>

 

<bean class="cn.itsource._01_.OtherBean"/>

 

</constructor-arg>

 

</bean>

.其它简单、集合属性注入

 

// 简单属性

 

private Long id;

 

private String name;

 

private Boolean sex;

 

private BigDecimal salary;

// 对象属性

private List<String> list;

private List<OtherBean> otherBeanList;

private Set<String> set;

private Set<OtherBean> otherBeanSet;

private Map<String,Object> map;

 

//下面这个是重点

private Properties props1;

private Properties props2;

private String[] arrays;

 数组(两种方案-掌握): 简写

<property name="arrays" value="A,B,C" />

 

 完整写法

<property name="arrays">

<array>

<value>xxx</value>

<value>yyy</value>

<value>zzz</value>

</array>

</property>

 

 List<String>(了解)

<property name="list">

<list>

<value>xxx</value>

<value>aaa</value>

<value>bbbb</value>

</list>

</property>

 

Set<String>(了解)

<property name="set">

<set>

<value>xxx</value>

<value>aaa</value>

<value>bbbb</value>

</set>

</property>

1.1. List<OtherBean>(了解)

<property name="otherBeanList">

<list>

<bean class="cn.itsource._01_.OtherBean" />

<bean class="cn.itsource._01_.OtherBean" />

<ref bean="otherBean" />

<ref bean="otherBean" />

</list>

</property>

1.1. Set<OtherBean>(了解)

<property name="otherBeanSet">

<set>

<bean class="cn.itsource._01_.OtherBean" />

<bean class="cn.itsource._01_.OtherBean" />

<ref bean="otherBean" />

<ref bean="otherBean" />

</set>

</property>

1.1. Map(了解)

<property name="map">

<map>

<entry key="key1" value-ref="otherBean"></entry>

     <entry key="key2" value="1234"></entry>

</map>

</property>

怎么配置一个Properties对象:

方案1  不支持中文

<property name="props1">

<value>

<!-- <value>

url jdbc:mysql:///xxx

username  xxxx

</value> -->

Jpa.dialect=org.Jpa.dialect.HSQLDialect

Jpa.driverClassName=com.mysql.jdbc.Driver

</value>

</property>

方案二:支持中文

<property name="props2">

<props>

<prop key="Jpa.dialect">org.Jpa.dialect.HSQLDialect</prop>

<prop key="Jpa.driverClassName">com.mysql.jdbc.Driver中文 </prop>

</props>

</property>

 

#xx.xml

{

  ...

  <bean id="person" class="x.xx.xx.Person">

    #此处必须与属性相同

    <property name="properties">  

      #使用props进行属性描述

      <props>

        <prop key="name">zhangsan</prop>

        <prop key="age">16</prop>

        <prop key="sex">male</prop>

      <props>

    </property >

  </bean>

  ...

}

XML自动注入

使用XML自动注入,可以简化我们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" default-autowire="byType">

    <!--

    beans标签(全局)

      default-autowire:自动注入

      byType : 字段类型必需和bean中的某一个类型相同

      如果用了byType,不允许出来两个类型相同的bean

      byName :  属性必需和bean的某一个id相同

    bean标签(局部)

     autowire(单独设置),有单独设置使用单独的,没有单独设置使用全局的

     -->

 <bean id="userDao" class="cn.itsource._04_autowire.UserDao"></bean>

   <bean id="userServices" class="cn.itsource._04_autowire.UserService">

   </bean>

   <bean id="userServicexxx" class="cn.itsource._04_autowire.UserService">

   </bean>

   <bean id="userAction" class="cn.itsource._04_autowire.UserAction" autowire="byName">

   </bean>

</beans>

1.1.1. byName : 按照属性的名:bean里提供定义一个属性,提供 setXxx方法   

         default-autowire="byName"

配置文件的beanid必须和代码bean里的属性一致。

1.1.2. byType   按照注入对象的类型,要求:类型只能配置一个实例

           default-autowire="byType"

setXxx方法   注入类的类型(Class)

           和配置文件里面的类型进行比较

           配置文件里面的类型只能是1

根节点beans   default-autowire="byName" 对当前配置文件的所有bean都生效

子节点bean autowire="byType"只对当前bean生效

全注解配置

配置context命名空间

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"

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

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context.xsd">

第一步:配置让Spring扫描类与支持注解

<!--

@Component  普通仓库

@Repository  仓库(其实就是dao层)

@Service service

@Controller  控制层(servletaction)

 -->

<!-- 进行包的扫描,去看类上面是否有相应的标签配置 -->

<context:component-scan base-package="cn.itsource._03_anno" />

<!-- 这个不是必须的(spring3.2版本前使用) 配上后兼容性好 -->

<context:annotation-config />

1.1. 调用名称两套方案:

1.1.1. 方案一:使用@Autowired

@Service

public class UserService {

@Autowired

@Qualifier("userJdbcDao")

private IUserDao userDao;

public void save(){

userDao.save();

}

}

 方案二:使用@Resource

@Service

public class UserService {

@Resource(name="userJpaDao")

private IUserDao userDao;

public void save(){

userDao.save();

}

}

AOP概述

 

AOP的使用只存在于一些特定的场合(具有横切逻辑的应用场合),横切逻辑这个解释可能比较抽象,咱们说得再具体一点,AOP可以用于事务管理,日志管理,性能监测等地方。

 

连接点(Joinpoint):程序执行的某一个特定位置,如类初始前后,方法的运行前后。而Spring只支持方法的连接点

 

切点(Pointcut):切点可以定位到相应的连接点,一个切点可以定位多个连接点。

 

增强(Advice):又被称为通知,完成逻辑的增强。

 

目标对象(Target):增强逻辑织入的目标类。

 

引介(Introduction):特殊的增强,为类添加一些属性和方法。

 

织入(Weaving): 将增强添加到目标类的具体连接点上的过程。Spring使用动态代理织入

 

代理(Proxy):一个类(原类)被织入增强(逻辑)后,就产生一个结果类,称为代理类。

 

切面(Aspect):由切点和增强组成

 

 

 

AOP联盟:众多开源AOP项目的联合组织,该组织定义了一套规范描述AOP标准。现在大部分的AOP实现都是使用AOP实现的标准。

 

 

 

1.1. Spring实现AOP的方案

Spring实现Aop有两种方案:JDKCGLIB

 若目标对象实现了若干接口

spring使用JDKjava.lang.reflect.Proxy类代理。

若目标对象没有实现任何接口,

spring使用CGLIB库生成目标对象的子类。

 

1.对接口创建代理优于对类创建代理,因为会产生更加松耦合的系统。

 

     对类代理是让遗留系统或无法实现接口的第三方类库同样可以得到通知,

 

            这种方案应该是备用方案。

 

 2.标记为final的方法不能够被通知。spring是为目标类产生子类。任何需要

 

             被通知的方法都被复写,将通知织入。final方法是不允许重写的。

 

1.1.1. 添加aop命名空间

xmlns:aop="http://www.springframework.org/schema/aop"

http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd

<aop:config>

<aop:pointcut expression="execution(* cn.itsource.aop.I*Service.*(..))" id="pointcut" />

<aop:aspect  ref="txManager">

<!-- 前置通知 -->

<aop:before method="begin" pointcut-ref="pointcut"/>

<!-- 后置通知 -->

<aop:after-returning method="commit" pointcut-ref="pointcut"/>

<!-- 异常通知 -->

<aop:after-throwing method="rollback" pointcut-ref="pointcut"/>

<!-- 最终通知 -->

<aop:after method="close" pointcut-ref="pointcut" />

</aop:aspect>

</aop:config>

环绕增强(前面的4个增强就不用了)

<!--

环绕通知:有了环绕,就不需要用另外几个通知(会重复)

       如果有两个以上的通知,建议使用环绕

 -->

<aop:around method="around" pointcut-ref="pointcut" />

 

 

 环绕方法

import org.aspectj.lang.ProceedingJoinPoint;

 

public Object around(ProceedingJoinPoint joinPoint){

//System.out.println(joinPoint.getTarget()); //调用的类

//System.out.println(Arrays.asList(joinPoint.getArgs()));//参递的参数

//System.out.println(joinPoint.getSignature()); //方法签名

Object object = null;

try {

begin();

object = joinPoint.proceed(); //执行相应的代码

commit();

} catch (Throwable e) {

rollback(e);

}finally{

close();

}

return object;

}

1.1. 注解版

1.1.1. 配置文件

 

<!-- 组件搜索 -->

 

<context:component-scan base-package="cn.itsource.aopanno" />

 

<!-- 支持aop注解 -->

 

<aop:aspectj-autoproxy />

1.1.1. 事务管理器

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.After;

import org.aspectj.lang.annotation.AfterReturning;

import org.aspectj.lang.annotation.AfterThrowing;

import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.Before;

import org.aspectj.lang.annotation.Pointcut;

import org.springframework.stereotype.Component;

 

@Component

@Aspect //AOP的类注解

public class TxManager {

//设置切点

@Pointcut("execution(* cn.itsource.aopanno.I*Service.*(..))")

public void pointcut(){}

//前置通知

@Before("pointcut()")

public void begin(){

System.out.println("开启事务....");

}

//后置通知

@AfterReturning("pointcut()")

public void commit(){

System.out.println("提交事务...");

}

//异常通知

@AfterThrowing(pointcut="pointcut()",throwing="e")

public void rollback(Throwable e){

System.out.println("回滚事务....");

System.out.println(e.getMessage());

}

//最终通知

@After("pointcut()")

public void close(){

System.out.println("关闭资源....");

}

}

//温馨提醒:如果要使用环绕通知的话,把其它几个通知的注解去掉(不然会出现重复)

@Around("pointcut()")

public Object around(ProceedingJoinPoint joinPoint){

Object object = null;

try {

begin();

object = joinPoint.proceed(); //执行相应的代码

commit();

} catch (Throwable e) {

rollback(e);

}finally{

close();

}

return object;

}

AOP是面向切面编程,是对咱们OOP的一个补充,SpringAop允许咱们在方法的前后加上相应的功能增强。

SpringAop是使用代理模式完成的,如果是有接口的类,使用JDK代理模式,如果没有接口的类,使用CGLIB代理模式。

咱们自己使用AOP太麻烦,Spring让我们通过简单的配置即可完成AOP

第一种配置:XML    第二种配置:注解

配置的时候注意找到何时(方法前后,异常),何地(哪些类的哪些方法),做什么(安全中是添加事务)

 

1.1. 代理模式定义

代理模式的英文叫做ProxySurrogate

① 抽象主题角色:

声明了真实主题和代理主题的共同接口,这样一来在任何可以使用真实主题的地方都可以是使用代理主题。

 

② 代理主题(Proxy)角色:

代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象;

代理主题角色提供一个与真实主题角色相同的接口,以便可以在任何时候都可以替代真实主题控制对真实主题的引用,负责在需要的时候创建真实主题对象(和删除真实主题对象);

代理角色通常在将客户端调用传递给真实的主题之前或之后(前置增强/通知,后置增强/通知),都要执行某个操作,而不是单纯地将调用传递给真实主题对象。

 

③ 真实主题角色:

定义了代理角色所代表地真实对象

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

猜你喜欢

转载自www.cnblogs.com/wzscom/p/10508273.html