spring01

Posted 曲阳阳

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring01相关的知识,希望对你有一定的参考价值。

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架

 

Spring的核心jar包

  spring-framework-3.2.0.RELEASE-dist.zip    -------Spring的核心包
  spring-framework-3.0.2.RELEASE-dependencies.zip  ------ Spring的依赖包

spring-core-3.2.2.RELEASE.jar:

包含Spring框架基本的核心工具类,Spring其它组件要都要使用到这个包里的类,是其它组件的基本核心

spring-beans-3.2.2.RELEASE.jar:

包含访问配置文件、创建和管理bean

以及进行Inversion of Control(IoC) / Dependency Injection(DI)操作相关的所有类

spring-expression-3.2.2.RELEASE.jar

Spring表达式语言
 

spring-context-3.2.2.RELEASE.jar

Spring提供在基础IoC功能上的扩展服务,此外还提供许多企业级服务的支持,

如邮件服务、任务调度、JNDI定位、EJB集成、远程访问、缓存以及各种视图层框架的封装等
 

com.springsource.org.apache.commons.logging-1.1.1.jar

第三方的主要用于处理日志

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

IOC&&DI

IOC控制反转的概念,就是将原本在程序中手动创建对象的控制权,交由Spring框架管理,即创建对象控制权被反转到了Spring框架

DI 依赖注入,在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件

 

BeanFactory && ApplicationContext

BeanFactory 才是 Spring 容器中的顶层接口。
ApplicationContext 是它的子接口。

区别:

  ApplicationContext:只要一读取配置文件,默认情况下就会创建对象。
  BeanFactory:什么使用什么时候创建对象

 

 

bean标签

 

作用:
  用于配置对象让 spring 来创建的。
  默认情况下它调用的是类中的无参构造函数。如果没有无参构造函数则不能创建成功。
属性:
  id: 给对象在容器中提供一个唯一标识。用于获取对象。
  class: 指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数。
  scope: 指定对象的作用范围。
    * singleton :默认值,单例的.
    * prototype :多例的.
    * request :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中.
    * session :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中.
    * global session :WEB 项目中,应用在 Portlet 环境.如果没有 Portlet 环境那么
globalSession 相当于 session.
    init-method: 指定类中的初始化方法名称。
    destroy-method: 指定类中销毁方法名称。

 

 

实例化bean的三种方式

 

使用构造方法实例化

1 使用默认无参构造函数
2 
3 根据默认无参构造函数来创建类对象。如果 bean 中没有默认无参构造函数,将会创建失败
4 
5 <bean id="accountService" class="com.xxx.service.impl.AccountServiceImpl"/>

 

使用静态工厂实例化

 1 /**
 2 * 模拟一个静态工厂,创建业务层实现类
 3 */
 4 public class StaticFactory {
 5 public static IAccountService createAccountService(){
 6 return new AccountServiceImpl();
 7   }
 8 }
 9 
10 <!-- 此种方式是:
11     使用 StaticFactory 类中的静态方法 createAccountService 创建对象,并存入 spring 容器
12     id 属性:指定 bean 的 id,用于从容器中获取
13     class 属性:指定静态工厂的全限定类名
14     factory-method 属性:指定生产对象的静态方法
15 -->
16 <bean id="accountService"
17 class="com.xxx.factory.StaticFactory"
18 factory-method="createAccountService"></bean>

 

使用实例工厂方法实例化

 1 /**
 2 * 模拟一个实例工厂,创建业务层实现类
 3 * 此工厂创建对象,必须现有工厂实例对象,再调用方法
 4 */
 5 public class InstanceFactory {
 6 public IAccountService createAccountService(){
 7     return new AccountServiceImpl();
 8     }
 9 }
10 <!-- 此种方式是:
11     先把工厂的创建交给 spring 来管理。
12     然后在使用工厂的 bean 来调用里面的方法
13         factory-bean 属性:用于指定实例工厂 bean 的 id。
14         factory-method 属性:用于指定实例工厂中创建对象的方法。
15 -->
16 <bean id="instancFactory"         
17         class="com.xxx.factory.InstanceFactory"></bean>
18     <bean id="accountService"
19 factory-bean="instancFactory"
20 factory-method="createAccountService"></bean>

 

 

Spring依赖注入方式

 

构造函数注入

 1 public class AccountServiceImpl implements IAccountService {
 2   private String name;
 3   private Integer age;
 4   private Date birthday;
 5 public AccountServiceImpl(String name, Integer age, Date birthday) {
 6   this.name = name;
 7   this.age = age;
 8   this.birthday = birthday;
 9 }
10 //
11 
12 }
13 
14 
15 <!--
16 
17 constructor-arg
18 属性:
19     index:指定参数在构造函数参数列表的索引位置
20     type:指定参数在构造函数中的数据类型
21     name:指定参数在构造函数中的名称
22     value:它能赋的值是基本数据类型和 String 类型
23     ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean
24 -->
25 
26 <bean id="accountService" class="com.xxx.service.impl.AccountServiceImpl">
27 <constructor-arg name="name" value="张三"></constructor-arg>
28 <constructor-arg name="age" value="18"></constructor-arg>
29 <constructor-arg name="birthday" ref="now"></constructor-arg>
30 </bean>
31 <bean id="now" class="java.util.Date"></bean>

 

Set方法注入‘

 1 public class User {
 2     private String username;
 3     private String password;
4 public String getUsername() { 5 return username; 6 } 7 public void setUsername(String username) { 9 this.username = username; 10 } 11 public String getPassword() { 12 return password; 13 } 14 public void setPassword(String password) { 15 this.password = password; 16 } 17 18 19 } 20 <!----
name:找的是类中 set 方法后面的部分
ref:给属性赋值是其他 bean 类型的
value:给属性赋值是基本数据类型和 string 类型的

----> 21 22 23 24 <bean id = "user" class= "com.xxx.model.User"> 25 <property name="username" value="gyf"></property> 26 <property name="password" value="123"></property> 27 28 </bean>

 

集合注入

 

也是set的注入方式

集合的注入都是给<property>添加子标签

                   数组:<array>

                   List:<list>

                   Set:<set>

                   Map:<map> ,map存放k/v 键值对,使用<entry>描述

                   Properties:<props>  <prop key=""></prop>  【】           

普通数据:<value>

引用数据:<r 1 public class Programmer {

 2     
 3     private List<String> cars;
 4     
 5     private Set<String> pats;
 6 
 7     private Map<String,String> infos; 
 8     
 9     private Properties mysqlInfos;
10     
11     private String[] members;
12       //setter getter
13     
14 }
15 
<!-- 注入集合数据
        List 结构的:
        array,list,set
        Map 结构的
        map,entry,props,prop
    -->
16 <bean id="programmer" class="com.xxx.model.Programmer"> 17 <property name="cars"> 18 <!-- list数据的注入 --> 19 <list> 20 <value>offo</value> 21 <value>mobai</value> 22 </list> 23 </property> 24 25 26 <property name="pats"> 27 <set> 28 <value>猫</value> 29 <value>狗</value> 30 </set> 31 </property> 32 33 <!-- Map数据的注入 --> 34 <property name="infos"> 35 <map> 36 <entry key="name" value="gyf"></entry> 37 <entry key="age" value="12"></entry> 38 <entry key="ip" value="127.0.0.1"></entry> 39 </map> 40 </property> 41 42 43 <!-- Properties属性注入 --> 44 <property name="mysqlInfos"> 45 <props> 46 <prop key="url">mysql:jdbc://localhost:3306/dbname</prop> 47 <prop key="user">root</prop> 48 <prop key="password">root</prop> 49 </props> 50 </property> 51 52 53 54 55 <!-- 数组参数注入 --> 56 <property name="members"> 57 <array> 58 <value>哥哥</value> 59 <value>弟弟</value> 60 <value>妹妹</value> 61 </array> 62 </property> 63 64 65 </bean>

 

注解注入

注解:就是一个类,使用@注解名称

开发中:使用注解 取代 xml配置文件。

 1 @Component
 2 @component取代<bean class="">
 3 
 4 
 5 @Component("id") 取代 <bean id="" class="">
 6 
 7 
 8 @Repository(“”):dao层
 9 @Service(“”):service层
10 @Controller(“”):web层
11 
12 @Autowired:自动根据类型注入      @Qualifier(“”):指定自动注入的id名称
13 @Resource(“名称”)
14 
15 @ PostConstruct 自定义初始化
16 @ PreDestroy 自定义销毁

 

 

Aop

面向切面编程。

 作用:
在程序运行期间,不修改源码对已有方法进行增强。

优势:
减少重复代码
提高开发效率
维护方便

 

术语

target:目标类,需要被代理的类。例如:UserService
Joinpoint(连接点):所谓连接点是指那些可能被拦截到的方法。例如:所有的方法
PointCut 切入点:已经被增强的连接点。例如:addUser()
advice 通知/增强,增强代码。例如:after、before
Weaving(织入):是指把增强advice应用到目标对象target来创建新的代理对象proxy的过程.
proxy 代理类
Aspect(切面): 是切入点pointcut和通知advice的结合 一个线是一个特殊的面。 一个切入点和一个通知,组成成一个特殊的面。

 

 

 

 

jdk动态代理&&cglib动态代理

基于接口的动态代理

 

提供者: JDK 官方的 Proxy 类。
要求:被代理类最少实现一个接口。

 

基于子类的动态代理

提供者:第三方的 CGLib,如果报 asmxxxx 异常,需要导入 asm.jar
要求:被代理类不能用 final
修饰的类(最终类)。

 

通知

 

前置通知 org.springframework.aop.MethodBeforeAdvice

         •在目标方法执行前实施增强

后置通知 org.springframework.aop.AfterReturningAdvice

         •在目标方法执行后实施增强

 

环绕通知 org.aopalliance.intercept.MethodInterceptor

         •在目标方法执行前后实施增强

 

 •异常抛出通知 org.springframework.aop.ThrowsAdvice

         •在方法抛出异常后实施增强

 

引介通知 org.springframework.aop.IntroductionInterceptor

         在目标类中添加一些新的方法和属性

1 环绕通知,必须手动执行目标方法
2 
3 try{
4    //前置通知
5    //执行目标方法
6    //后置通知
7 } catch(){
8    //抛出异常通知
9 }

 

Aop配置

 1 IAccountService
 2 
 3 AccountServiceImpl
 4 
 5  <!-- 配置srping的Ioc,把service对象配置进来-->
 6     <bean id="accountService" class="com.xxx.service.impl.AccountServiceImpl"></bean>
 7 
 8 
 9 <!--spring中基于XML的AOP配置步骤
10         1、把通知Bean也交给spring来管理
11         2、使用aop:config标签表明开始AOP的配置
12         3、使用aop:aspect标签表明配置切面
13                 id属性:是给切面提供一个唯一标识
14                 ref属性:是指定通知类bean的Id。
15         4、在aop:aspect标签的内部使用对应标签来配置通知的类型
16                我们现在示例是让printLog方法在切入点方法执行之前之前:所以是前置通知
17                aop:before:表示配置前置通知
18                     method属性:用于指定Logger类中哪个方法是前置通知
19                     pointcut属性:用于指定切入点表达式,该表达式的含义指的是对业务层中哪些方法增强 -->
20     <!-- 配置Logger类,切面类 -->
21     <bean id="logger" class="com.itheima.utils.Logger"></bean>
22 
23     <!--配置AOP-->
24     <aop:config>
25         <!--配置切面 -->
26         <aop:aspect id="logAdvice" ref="logger">
27             <!-- 配置通知的类型,并且建立通知方法和切入点方法的关联-->
28             <aop:before method="printLog" pointcut="execution(* com.itheima.service.impl.*.*(..))"></aop:before>
29         </aop:aspect>
30     </aop:config>

 切入点表达式的写法:

 

 关键字:execution(表达式)

表达式:

访问修饰符 返回值 包名.包名.包名...类名.方法名(参数列表)

public void com.xxx.service.impl.AccountServiceImpl.saveAccount()

访问修饰符可以省略    void com.xxx.service.impl.AccountServiceImpl.saveAccount()

返回值可以使用通配符   ,表示任意返回值

包名可以使用通配符,表示任意包。但是有几级包,就需要写几个*.

*    * .* .*. *. AccountServiceImpl.saveAccount())

包名可以使用..表示当前包及其子包
 *  *. . AccountServiceImpl.saveAccount()

类名和方法名都可以使用*来实现通配
*  *. . * . * ()

参数列表:
可以直接写数据类型:
  基本类型直接写名称 int
  引用类型写包名.类名的方式 java.lang.String
      可以使用通配符表示任意类型,但是必须有参数
         可以使用 . .  表示有无参数均可,有参数可以是任意类型

         ()                                                     无参

         (int)                                                一个整型

         (int ,int)                                         两个

         (..)                                                   参数任意


全通配写法:

 * *. .*.*(. .)

通常写法:切到业务层实现类下的所有方法
* com.xxx.service.impl.*.*(..)

 

 

基于注解的aop

bean.xml

1     <!-- 配置spring创建容器时要扫描的包-->
2     <context:component-scan base-package="com.xxx"></context:component-scan>
3 
4     <!-- 配置spring开启注解AOP的支持 -->
5     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

替换service和切面bean

@Service

@Component

 

@Aspect//表明当前类是一个切面类

 

在增强的方法上使用注解配置通知

@Before
作用:
把当前方法看成是前置通知。
属性:
 value:用于指定切入点表达式,还可以指定切入点表达式的引用。

      @Before("execution(* com.xxx.service.impl.*.*(..))")

 

@AfterReturning 把当前方法看成是后置通知。

@Around :把当前方法看成是环绕通知

 

@Pointcut  指定切入点表达式

 1 @Aspect  声明切面,修饰切面类,从而获得 通知。
 2 
 3 @Before 前置
 4 
 5          @AfterReturning 后置
 6 
 7          @Around 环绕
 8 
 9          @AfterThrowing 抛出异常
10 
11          @After 最终
12 
13 切入点 @PointCut ,修饰方法 private void xxx(){}  之后通过“方法名”获得切入点引用

 

 

 

 

 

 

 

 

 

 

 

 

 

以上是关于spring01的主要内容,如果未能解决你的问题,请参考以下文章

初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段

Spring boot:thymeleaf 没有正确渲染片段

What's the difference between @Component, @Repository & @Service annotations in Spring?(代码片段

spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象(代码片段

Spring Rest 文档。片段生成时 UTF-8 中间字节无效 [重复]

解决spring-boot启动中碰到的问题:Cannot determine embedded database driver class for database type NONE(转)(代码片段