SpringFramework概述及IOC

4 篇文章 0 订阅
2 篇文章 0 订阅

一:Spring概述、Spring体系介绍

Spring的核心是控制反转(IoC)和面向切面(AOP)

spring是开源的、轻量级的、一站式的框架,以 IoC(Inverse Of Control: 反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核

二:Spring安装配置

在工程目录下的pom.xml中配置

<dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-context</artifactId>
     <version>5.2.0.RELEASE</version>
  </dependency>

可在网上查找,粘贴过来

三:IOC

IOC容器初始化

ApplicationContext实现类

ApplicationContext是一个接口,有以下几个不同的实现类:

ClassPathXmlApplicationContext

AnnotationConfigApplicationContext

FileSystemXmlApplicationContext
XmlWebApplicationContext
ClassPathXmlApplicationContext
使用方法:
  1. 创建实体类

    package com.lanou3g.bean;
    
    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class Man {
        private Food name;
        private String hobby;
        private int age;
        private String sex;
        private String food;
    
        public void eat(){
            System.out.println("我叫" + name + ",我今年" + age + "岁了,我喜欢吃:" + food);
        }
    
        public void play(){
            System.out.println("我叫" + name + ",我今年" + age + "岁了,我喜欢玩:" + hobby);
        }
    
    }
    
    
  2. 配置Spring 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">
        <bean id="man" class="com.lanou3g.bean.Man">
            <property name="age" value="18"></property>
            <property name="food" value="橘子"></property>
            <property name="hobby" value="吃鸡"></property>
    <!--        <property name="name" value="赵云"></property>-->
            <property name="name" ref="apple"></property>
            <property name="sex" value=""></property>
        </bean>
        <bean id="apple" class="com.lanou3g.bean.Food">
            <property name="name" value="张飞"></property>
        </bean>
    </beans>
    
  3. 使用

    public class App {
        public static void main( String[] args ) {
            useSpringIOC();
    
        }
        public static void useSpringIOC(){
            //加载Spring上下文配置文件
            ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
            //获取bean
            Man man = (Man) cxt.getBean("man");
            Man man1 = cxt.getBean("man",Man.class);
            Man man2 = cxt.getBean(Man.class);
    
            man.eat();
            man.play();
            System.out.println("man:" + man);
            System.out.println("man1:" + man1);
            System.out.println("man2:" + man2);
        }
    }
    

    如果是两个xml文件以上,可以使用字符串数组

    ApplicationContext cxt = new ClassPathXmlApplicationContext(new String[]{“applicationContext.xml”,“applicationContext1.xml”});

    或者使用通配符

    ApplicationContext cxt = new ClassPathXmlApplicationContext(“classpath:/*.xml”);

AnnotationConfigApplicationContext
使用方法:
  1. 创建实体类

    package com.lanou3g.bean;
    
    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class Student {
        private String name;
        private int age;
    }
    
    
  2. 创建@Configuration配置类

    package com.lanou3g;
    
    import com.lanou3g.bean.Student;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration //表明是bean的配置类
    public class AppConfig {
        @Bean
        public Student student1(){ //方法名相当于id
            Student student = new Student();
            student.setName("张三");
            student.setAge(18);
            return student;
        }
    
        @Bean
        public Student student2(){
            Student student = new Student();
            student.setName("赵云");
            student.setAge(20);
            return student;
        }
    }
    
    

    @configuration可理解为用Spring的时候xml里面的标签

    @Bean可理解为用Spring的时候xml里面的标签

  3. 使用

    public class App {
        public static void main( String[] args ) {
           // useSpringIOC();
            useSpringIOC2();
    
        }
    
    public static void useSpringIOC2(){
         AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("AppConfig.class");
            Student student1 = (Student) ctx.getBean("student1");
            System.out.println(student1.getName());
            System.out.println(student1.getAge());
    
            Student student2 = (Student) ctx.getBean("student2");
            System.out.println(student2.getName());
            System.out.println(student2.getAge());
        }
    }
    
FileSystemXmlApplicationContext
XmlWebApplicationContext

这两种跟上面的类似

Application初始化路径

路径前缀
//	前缀classpath:表示的是项目的classpath下相对路径   
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
路径中的通配符
//	使用通配符加载所有符合要求的文件  
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath*:applicationContext.xml");


通过Xml方式配置管理bean

schema约束地址不能用https,否则每次都要从Spring加载,无网不能运行(新版本已解决这个问题)

使用步骤:

  • 创建实体类
  package com.lanou3g.bean;
  
  import lombok.Getter;
  import lombok.Setter;
  
  @Getter
  @Setter
  public class Man {
      private String hobby;
      private int age;
      private String sex;
      private String food;
  
      public void eat(){
          System.out.println("我叫" + name + ",我今年" + age + "岁了,我喜欢吃:" + food);
      }
  
      public void play(){
          System.out.println("我叫" + name + ",我今年" + age + "岁了,我喜欢玩:" + hobby);
      }
  }
  
  

  • 配置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">
        <bean id="man" class="com.lanou3g.bean.Man">
            <property name="age" value="18"></property>
            <property name="food" value="橘子"></property>
            <property name="hobby" value="吃鸡"></property>
            <property name="name" ref="apple"></property>
            <property name="sex" value=""></property>
        </bean>   
    </beans>    

通过注解方式管理bean

两种方式:
第一种:
  1. 创建实体类
   package com.lanou3g.bean;
   
   import lombok.Getter;
   import lombok.Setter;
   import org.springframework.stereotype.Component;
   
   @Component //把普通实体类实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>
   @Getter
   @Setter
   public class Student {
       private String name;
       private int age;
   }
   

  1. 创建配置类
   package com.lanou3g;
   
   import com.lanou3g.bean.Student;
   import org.springframework.context.annotation.Bean;
   import org.springframework.context.annotation.ComponentScan;
   import org.springframework.context.annotation.Configuration;
   
   @Configuration //表明该类是Spring的一个配置类,该类中会包含应用上下文创建bean的具体细节
   @ComponentScan(basePackages = "com.lanou3g")//开启注解扫描支持,同时指定扫描包根路径
   public class MyConfiguration {
   
   }
   
   

  1. 使用
   package com.lanou3g;
   
   import com.lanou3g.bean.Student;
   import org.springframework.context.ApplicationContext;
   import org.springframework.context.annotation.AnnotationConfigApplicationContext;
   
   public class App {
       public static void main( String[] args ) {
           //加载Spring上下文配置文件
           ApplicationContext cxt = new AnnotationConfigApplicationContext(MyConfiguration.class);
           testIOCBean(cxt);
       }
   
       public static void testIOCBean(ApplicationContext cxt){
           //获取bean
           Student stu = cxt.getBean(Student.class);
           System.out.println(stu.getName());
           System.out.println(stu.getAge());
       }
   }
   

第二种:
  1. 创建实体类
   package com.lanou3g.bean;
   
   import lombok.Getter;
   import lombok.Setter;
   
   @Getter
   @Setter
   public class Student {
       private String name;
       private int age;
   }
   

  1. 创建配置类
   package com.lanou3g;
   
   import com.lanou3g.bean.Student;
   import org.springframework.context.annotation.Bean;
   import org.springframework.context.annotation.Configuration;
   
   //加上@Configuration注解后,这个类就相当于变成了一个Spring上下文配置文件
   @Configuration
   public class AppConfig {
       @Bean
       public Student student1(){//方法名相当于id
           Student student = new Student();
           student.setName("张三");
           student.setAge(18);
           return student;
       }
   
       @Bean
       public Student student2(){
           Student student = new Student();
           student.setName("赵云");
           student.setAge(20);
           return student;
       }
   }
   

@configuration可理解为用Spring的时候xml里面的标签

@Bean可理解为用Spring的时候xml里面的标签

  1. 使用
   public class App {
       public static void main( String[] args ) {
          // useSpringIOC();
           useSpringIOC2();
   
       }
   
   public static void useSpringIOC2(){
           AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("AppConfig.class");    
           Student student1 = (Student) ctx.getBean("student1");
           System.out.println(student1.getName());
           System.out.println(student1.getAge());
   
           Student student2 = (Student) ctx.getBean("student2");
           System.out.println(student2.getName());
           System.out.println(student2.getAge());       
       }
   }

注意:
package com.lanou3g.service;

import com.lanou3g.bean.Student;
import com.lanou3g.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service //自动扫描(注入dao)
public class StudentService {
    @Autowired //自动装配
    private StudentDao studentDao;

    public Student getStudentById(Integer id) {
        return studentDao.findStuById(id);
    }
}



在一个配置中导入另一个配置

xml中导入其他xml配置
这是application  xml的配置
<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">

    <!-- 导入其他spring配置的.xml文件 -->
    <import resource="classpath:other.xml" />

</beans>


other.xml的配置
<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">

</beans>


注解方式导入
导入其他注解配置
  1. 创建Dog和Cat类

    package com.example.demo;
    
    @Configuration
    public class Dog {
     
    }
    
    
    package com.example.demo;
    
    @Configuration
    public class Cat {
     
    }
    
    
    
  2. 在启动类中需要获取Dog和Cat对应的bean,需要用注解@Import注解把Dog和Cat的bean注入到当前容器中。

    package com.example.demo;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Import;
     
    @ComponentScan
    /*把用到的资源导入到当前容器中*/
    @Import({Dog.class, Cat.class})
    public class App {
     
        public static void main(String[] args) throws Exception {
     
            ConfigurableApplicationContext context = SpringApplication.run(App.class, args);
            System.out.println(context.getBean(Dog.class));
            System.out.println(context.getBean(Cat.class));
            context.close();
        }
    }
    
    
    
导入xml配置

还是上面的Dog和Cat类,现在在一个配置类中进行配置bean,然后在需要的时候,只需要导入这个配置就可以了,最后输出结果相同。

  1. MyConfig 配置类:

    package com.example.demo;
    import org.springframework.context.annotation.Bean;
     
    public class MyConfig {
     
        @Bean
        public Dog getDog(){
            return new Dog();
        }
     
        @Bean
        public Cat getCat(){
            return new Cat();
        }
     
    }
    
    
    
  2. 若在启动类中要获取Dog和Cat的bean,如下使用:

    package com.example.demo;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Import;
     
    @ComponentScan
    /*导入配置类就可以了*/
    @Import(MyConfig.class)
    public class App {
     
        public static void main(String[] args) throws Exception {
     
            ConfigurableApplicationContext context = SpringApplication.run(App.class, args);
            System.out.println(context.getBean(Dog.class));
            System.out.println(context.getBean(Cat.class));
            context.close();
        }
    }
    
    
    

深入了解IOC

管理bean的作用域

img

scope:配置bean的作用域

<bean id="man" class="com.lanou.spring.bean.Man" scope="prototype">
       
    </bean>


singleton(默认)

单例。整个IOC容器中只有一个bean的实例,而且该bean的实例会在IOC容器实例化的时候创建。

<bean id="man" class="com.lanou.spring.bean.Man" scope="singleton">
        <property name="age" value="26" /> 
        <property name="hobby" value="吃饭,睡觉" />
        <property name="gender" value="" />
        <property name="name" value="孙尚香" />
    	<!--引用-->
    	<property name="food" ref="apple" />
    </bean>


prototype

原形。整个IOC容器中有多个bean的实例,在容器初始化的时候不会创建,只有通过getBean方法获取bean的实例时,IOC容器都会创建一个新的对象返回。

<bean id="man" class="com.lanou.spring.bean.Man" scope="prototype">
        <property name="age" value="26" />
        <property name="hobby" value="吃饭,睡觉" />
        <property name="gender" value="" />
        <property name="name" value="孙尚香" />
    	<!--引用-->
    	<property name="food" ref="apple" />
    </bean>


管理bean的生命周期
  • Singleton Bean的生命周期

     <bean id="zhangFei" class="com.lanou.spring.bean.Man" init-method="init" destroy-method="destroy">
            <property name="name" value="张飞" />
      </bean>
    
    
    

    scope:singleton单例模式的生命周期,默认IOC容器初始化的时候就会调用init

  • Prototype Bean的生命周期

    • 初始化时机: 在实际使用该bean的时候,比如:getBean、获取依赖此bean的其他bean需要使用
    • 销毁时机: 在IOC容器销毁时。(但是通过destroy-method指定的声明周期方法不会被调用,也就是说Spring不提供prototypebean完整的生命周期管理)
  • 如何指定生命周期的回调方法

    • xml中的init-method、destory-method
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    
    
    • 注解方式@PostConstrutor、@PreDetory

      @PostConstruct注解Bean中的某些方法,可以用在服务器启动时的做一些初始化工作。

  import javax.annotation.PostConstruct;
   
  import org.apache.log4j.Logger;
  import org.springframework.stereotype.Service;
   
  @Service("bean1")
  public class Bean1 {
  	
  	private static final Logger log = Logger.getLogger(Bean1.class);	
  	
  	@PostConstruct
  	public void test() {
  		
  	}
      
      @PreDetory
  	public void test1() {
  		
  	}
  }

  • 指定默认的声明周期回调方法
    • 在xml中,通过在beans标签上添加default-init-method、default-destory-method来指定
    • 在注解配置中,没有对应的方法可以设置所有bean默认的生命周期回调
id和name命名的bean
  • 在XML中配置中可以通过标签上的id、name属性值给一个bean命名,以便在其他地方引用。
  • id属性: bean的唯一名称,只允许出现一个值。且同一个IOC容器中不允许出现两个id值一样的bean。
  • name属性: 和id类似也是给bean命名。但是name属性的值可以有多个,多个值之间使用英文逗号或者英文分号或者空格符隔开
实例化bean的方式
  • 构造方法

  • 静态工厂方法

    • 创建实体类
      package com.lanou3g;
      
      import lombok.Getter;
      
      @Getter
      public class Women {
          private String name;
      
          public Women(String name) {
              this.name = name;
          }
      }
      
      
    
    
    • 创建工厂
      package com.lanou3g.factory;
      
      import com.lanou3g.Women;
      
      public class WomenFactory {
          public Women newInstance(String name) {
              return new Women(name);
          }
      }
      
      
    
    
    • 配置xml
    <bean id="women" class="com.lanou3g.factory.WomenFactory" factory-method="newInstance">
            <constructor-arg name="name" value="张三" />
     </bean>
    
    
    
  • 实例工厂方法

    • 创建实体类
      package com.lanou3g;
      
      import lombok.Getter;
      
      @Getter
      public class Women {
          private String name;
      
          public Women(String name) {
              this.name = name;
          }
      }
      
    
    
    • 创建工厂
      package com.lanou3g.factory;
      
      import com.lanou3g.Women;
      
      public class WomenFactory {
          public static Women newInstance(String name) {
              return new Women(name);
          }
      }
      
    
    
    • 配置xml
      <!-- 使用实例工厂方法创建bean对象 -->
          <!-- Spring中无法使用对象的方式去调用静态工厂方法,比如下面这么写就不行 -->
          <!--    <bean id="womenFactory" class="com.lanou3g.factory.WomenStaticFactory" />-->
          <bean id="womenFactory" class="com.lanou3g.factory.WomenFactory" />
          <bean id="xiaoFang" factory-bean="womenFactory" factory-method="newInstance">
              <constructor-arg name="name" value="小芳" />
          </bean>
      
    
    

优雅的关闭IOC容器

添加一个shutdown hook。所有派生自ConfigurableApplicationContext接口的实现类都支持此方法

ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("xxx.xml");

ctx.registerShutdownHook(); //注册停止回调


懒加载

懒加载配置主要是针对单例的bean,因为它默认是在容器初始化时就被实例化了。

  • lazy-init属性(默认是false)

spring-di-xml配置方式

构造方法注入

创建java类

package com.lanou3g.bean;

import lombok.Getter;
import lombok.Setter;

import java.util.List;
import java.util.Map;

@Setter
@Getter
public class Man {
    private String name;
    private Man gf;
    private List<String> hobbies;
    private Map<String, String> gameTitle;

    public Man() {}

    public Man(String name) {
        this.name = name;
    }
}


package com.lanou3g.bean;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class User {
    private String username;
    private String password;
    private String email;
}

创建UserDao

package com.lanou3g.dao;

import com.lanou3g.bean.User;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.sql.SQLException;
import java.util.List;

@Component
public class UserDao {
    @Autowired
    private QueryRunner queryRunner;

    public List<User> selectAll() {
        String sql = "select username, password, email from user;";
        try {
            List<User> userList = queryRunner.query(sql, new BeanListHandler<User>(User.class));
            return userList;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}


有参
    <!-- 带参数的构造方法创建bean -->
    <!-- 使用constructor-arg注入构造参数 -->
    <!--<bean id="queryRunner"           	class="org.apache.commons.dbutils.QueryRunner">
        <constructor-arg name="ds" ref="dataSource" />
    </bean>-->
    <bean id="lisi" class="com.lanou3g.spring.bean.Man">
        <constructor-arg name="name" value="李四" />
    </bean>

测试代码

import com.lanou3g.bean.Man;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

public class testInjection extends BaseTest{
    @Autowired
    private ApplicationContext ctx;
    /**
     *构造方法注入
     */
    @Test
    public void testConstructorInjection(){
        Man zhangsan = ctx.getBean("zhangsan", Man.class);
        Man lisi = ctx.getBean("lisi", Man.class);
        System.out.println(ReflectionToStringBuilder.toString(zhangsan));
        System.out.println(ReflectionToStringBuilder.toString(lisi));
    }
}

无参
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner"/>

测试代码

package com.lanou3g;

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import javax.sql.DataSource;

public class TestBaseTest extends BaseTest{
    @Autowired
    private DataSource dataSource;

    @Test
    public void testConnectionPool(){
        System.out.println(dataSouce);
    }
}

通过c命名空间注入参数

原来的头部

<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>

c命名空间的头部

<beans xmlns="http://www.springframework.org/schema/beans"   xmlns:context="http://www.springframework.org/schema/context"
<!--添加的-->
xmlns:c="http://www.springframework.org/schema/c"

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">
<!--加载文件-->
<context:property-placeholder location="jdbc.properties"/>
<!--自动扫描文件-->
<context:component-scan base-package="com.lanou3g"/>

c命名空间的使用

<!-- 使用c命名空间来注入构造参数(请注意文件头的schema) -->
    <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner" c:ds-ref="dataSource" />
    <bean id="zhangsan" class="com.lanou3g.spring.bean.Man" c:name="张三" />

setter注入

支持注入的类型
  • 普通字面量
    • String
    • Integer(int)
    • Long(long)
    • Byte(byte)
setter方法注入参数

外层用包裹,内部属性用或者

<!-- setter方法注入参数 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.user}" />
        <property name="password" value="${jdbc.password}" />
        <property name="driverClassName" value="${jdbc.driver}" />
        <property name="filters" value="stat" />

        <property name="maxActive" value="20" />
        <property name="initialSize" value="1" />
        <property name="maxWait" value="60000" />
        <property name="minIdle" value="1" />

        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        <property name="minEvictableIdleTimeMillis" value="300000" />

        <property name="testWhileIdle" value="true" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />

        <property name="poolPreparedStatements" value="true" />
        <property name="maxOpenPreparedStatements" value="20" />

        <property name="asyncInit" value="true" />
    </bean>

使用实例

import com.lanou3g.bean.Man;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

public class testInjection extends BaseTest{
    @Autowired
    private ApplicationContext ctx;
    @Test
    public void testSetterInjection(){
        Man xiaohong = ctx.getBean("xiaohong", Man.class);
        System.out.println(ReflectionToStringBuilder.toString(xiaohong));
    }
}

注入匿名内部bean

外层用包裹,内部属性用或者

,在或者内部再包裹

<!-- 使用内部bean注入 -->
    <bean id="xxx" class="com.lanou3g.spring.bean.Man">
        <property name="name" value="张三" />
        <property name="gf">
            <!-- 内部bean只能在这里使用,别的地方无法引用,即使有id属性也不行 -->
            <bean id="yyy" class="com.lanou3g.spring.bean.Man" p:name="李四" />
        </property>
    </bean>

使用示例

import com.lanou3g.bean.Man;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

public class testInjection extends BaseTest{
    @Autowired
    private ApplicationContext ctx;
   /**
     * 测试内部bean
     */
    @Test
    public void testInnerBeanInjection(){
        Man kangJian = ctx.getBean("xxx", Man.class);
        System.out.println(kangJian.getName() + "的GF是" + kangJian.getGf().getName());
    }
}

通过p命名空间注入属性

原来的头部

<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>

p命名空间的头部

<beans xmlns="http://www.springframework.org/schema/beans"   xmlns:context="http://www.springframework.org/schema/context"
<!--添加的-->
xmlns:p="http://www.springframework.org/schema/p"

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">
<!--加载文件-->
<context:property-placeholder location="jdbc.properties"/>
<!--自动扫描文件-->
<context:component-scan base-package="com.lanou3g"/>

使用

<!-- 使用p命名空间注入属性 -->
<bean id="xiaohong" class="com.lanou3g.bean.Man" p:name="xaiohong"/>


注入集合类型属性

实体类类中有一个属性为数组类型或list(map)等,如:

package com.lanou3g.bean;import lombok.Getter;import lombok.Setter;import java.util.List;import java.util.Map;@Setter@Getterpublic class Man {    private String name;    
private Man gf;    
private List<String> hobbies;   
private Map<String, String> gameTitle;                                                                       
public Man() {

}   

public Man(String name) {        
this.name = name;    
}
}


<!--注入集合类型属性-->
    <bean id="xiaoMing" class="com.lanou3g.bean.Man">
        <!--List-->
        <property name="hobbies">
            <list>
                <value>简单类型值</value>
                <bean>内部bean</bean>
                <ref bean="xxx" />
            </list>
        </property>
        <!--Map-->
        <property name="gameTitle">
            <map>
                <entry key="王者荣耀" value="倔强青铜"/>
                <entry key="吃鸡" value="超级王牌"/>
            </map>
        </property>
        <!--Set-->
        <property name="hobbies">
    	<!-- set用法和List类似, 里面可以注入普通字面量值、也可以是一个bean引用,或者内部bean、或者是一个set、list、Properties  -->
        <set>
        	<value>简单类型值</value>
            <bean>内部bean</bean>
            <ref bean="xxx" />
        </set>
    </property>
      <!--java.util.Properties-->
      <!-- props标签是用来注入java.util.Properties类型的属性,用法和map类似,但是属性值是在标签中间写 -->
        <property name="gameNick">
            <props>
                <prop key="王者荣耀">最擅长1V5</prop>
                <prop key="吃鸡">一枪爆头</prop>
            </props>
		</property>
</bean>


使用

package com.lanou3g;

import com.lanou3g.bean.Man;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

public class testInjection extends BaseTest{
    @Autowired
    private ApplicationContext ctx;
    @Test
    public void testCollectionInjection(){
        /**
         * 使用list注入集合属性
         */
        Man xiaoMing = ctx.getBean("xiaoMing", Man.class);
        System.out.println(xiaoMing.getName() + "的爱好是" + xiaoMing.getHobbies());
        
        /**
         * 使用Map注入集合属性
         */
        System.out.println(xiaoMing.getName() + "的游戏段位是:" + xiaoMing.getGameTitle());
    }
}


注入null、空字符串类型属性值
<bean id="xiaoMing" class="com.lanou3g.bean.Man">
    <!--注入空值和null-->
        <property name="marrayStatus" value=""/>
        <property name="gender">
            <null/>
        </property>
</bean>


使用

package com.lanou3g;

import com.lanou3g.bean.Man;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

public class testInjection extends BaseTest{
    @Autowired
    private ApplicationContext ctx;
	/**
     * 注入null、空字符串类型属性值
     */
    @Test
    public void testNullOrEmptyInjection(){
        Man man = ctx.getBean("xiaoMing",Man.class);
        System.out.println(man.getName()+"婚姻状况:" + man.getMarrayStatus()+", 字段值长度:" + man.getMarrayStatus().length());

        System.out.println(man.getName()+"性别:" + man.getGender());
    }
}


注入复合属性
<bean id="xiaoMing" class="com.lanou3g.bean.Man">
    <!-- 注入复合属性 -->
       <property name="username">
           <bean class="com.lanou3g.bean.User" />
       </property>
       <property name="username.username" value="三国演义"/>
</bean>


使用

package com.lanou3g;

import com.lanou3g.bean.Man;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

public class testInjection extends BaseTest{
    @Autowired
    private ApplicationContext ctx;
	/**
     * 注入复合属性
     */
    @Test
    public void testComboPropertyInjection() {
        Man man = ctx.getBean("xiaoMing", Man.class);
        System.out.println(man.getName() + "最喜欢看的一本书:" + man.getUsername().getUsername());
    }
}


注入外部properties文件中的属性值
<bean id="xiaoMing" class="com.lanou3g.bean.Man">
    <property name="gameNick">
          <props>
             <prop key="王者荣耀">最擅长1V5</prop>
              <prop key="吃鸡">一枪爆头</prop>
           </props>
      </property>
</bean>


自动装配

自动装配支持的策略
使用autowire属性可以开启自动注入(不需要显式使用setter、构造方法注入属性值)可选的自动注入策略有四个:    
    no: 不自动注入(默认值)   
    byType: 自动根据属性类型去IOC中寻找,如果找到的匹配类型多于一个会             报错  
    byName: 根据setter方法的名称去IOC中找bean的名称对应的,如果找               到,就自动注入;否则不注入    
    constructor: 类似于byType,但是注入的地方是构造方法的参数。      查找流程:               
   首先按照所需参数类型去IOC容器中查找,如果只找到一个就自动装配;如果有多个匹配的类型,就按照参数的名称进一步筛查;如果没有找到一个匹配的类型,就报错。


<!--构建bean-->
<bean class="com.lanou3g.dao.UserDao"autowire="constructor">
</bean>

<bean id="xh" class="com.lanou3g.bean.Man" p:name="小红" autowire="constructor" />


将某个类从自动装配候选中排除

当按照类型自动装配时,如果有多个匹配类型的bean满足条件,我们可以给候选的bean添加autowire-candidate属性,让其退出竞争。

开启自动装配
<!-- 
通过给当前的bean添加autowire属性开启自动注入
可选的值:参见自动装配章节
 -->
<bean id="xx" class="" autowire="" />


提高自动装配时的权重
<!-- 当其他的bean中需要注入一个Test类型的属性,而满足条件的bean有多个时,会优先注入primary="true"的bean -->
<bean id="xx" class="com.Test" primary="true" />


注解方式提高自动装配时的权重
@Primary
@Component
public class Test {


}

public class Main {
    
    @Primary
    @Bean
    public void test() {
        return new Test();
    }
    
}


按类型自动装配时,不参与候选
!-- 当其他的bean中需要注入一个Test类型的属性,而满足条件的bean有多个时,autowire-candidate="false"的bean会自动退出候选序列 -->
<bean id="xx" class="com.Test" autowire-candidate="false" />


spring-di-注解配置方式

创建实体类

package com.lanou3g.bean;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class User {
    private String username;
    private String password;
    private String email;
}


package com.lanou3g.bean;

import lombok.Getter;
import lombok.Setter;

import java.util.List;
import java.util.Map;

@Setter
@Getter
public class Man {

    public Man(User username) {
        this.username = username;
    }

    private String name;
    private Man gf;
    private List<String> hobbies;
    private Map<String, String> gameTitle;
    private String marrayStatus;
    private String gender;
    private User username;

    public Man() {}

    public Man(String name) {
        this.name = name;
    }
}


创建dao

package com.lanou3g.dao;

import com.lanou3g.bean.User;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import java.sql.SQLException;
import java.util.List;

//@Component
//把普通Java类实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>
@Repository 
public class UserDao {
    @Autowired //自动注入
    private QueryRunner queryRunner;

    public List<User> selectAll() {
        String sql = "select username, password, email from user;";
        try {
            List<User> userList = queryRunner.query(sql, new BeanListHandler<User>(User.class));
            return userList;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}


@Configuration

标识一个类作为Spring的一个bean配置文件

@componentScan

指定要扫描哪些包下的注解,相当于xml中的

<context:component-scope base-packag=“org.example” />

@Autowired

开启自动注入功能

默认是byType注入。如果候选的bean多于一个,则会报错。 可以配合@Qualifier注解实现byName注入。

常用属性:

  • required: 注入的属性是否是必要的,默认是true。必要注入属性如果没有找到可以注入的目标bean,会直接报错。
@Autowired(required = false) //required默认是true
private QueryRunner queryRunner;

@PropertySource

将外部的properties引入IOC容器,配合@value属性自动将properties中的属性注入到类中使用@value注解的属性上

@PropertySource(“classpath:/jdbc.properties”)

注意后面的格式

@Configuration //标识一个类作为spring的一个bean文件
@ComponentScan(basePackages = "com.lanou3g") //指定要扫描哪些包下的注解
//将外部的properties引入IOC容器,配合@value属性自动将properties中的属性注入到类中使用@value注解的属性上
@PropertySource("classpath:/jdbc.properties")

@Qualifier

有两个作用:

  • 配合@Autowired注解使用, 将自动注入方式由byType改成byName
  • 配合@Bean使用,给bean命名
    @Autowired
    @Qualifier("miYue")//此注解配合上面的自动注入注解(代表按照名称                           注入bean byName)
    private Girl girl;

    @Bean
    public Girl miYue() {
        return new Girl("芈月");
    }

@Resource

  • 这是JSR-250规范里的原生注解,Spring也支持用此注解实现自动注入
  • 此注解的工作原理:先按照byName模式去查找bean,如果没找到自动切成成byType模式
  • 相当于 @Autowired和@Qualifier(“miYue”)合用
    @Autowired
    @Resource
    private Girl girl;

    @Bean
    public Girl girl() {
        return new Girl("芈月");
    }

    @Bean
    @Primary
    public Girl meiNiang() {
        return new Girl("媚娘");
    }

输出结果芈月,因为芈月的方法名字是girl

@Component

这个注解会将该类的对象交由IOC容器来管理
相当于在xml中配置了一个bean

在不同层有不同的专用注解

@Service 业务层

@Repository 持久层

@Controller 控制层

@Scope

@Scope(scopeName = “prototype”) //指定作用域(相当于xml中bean的scope属性)

@Bean

将一个bean交由ioc管理, 和@Component的区别是:

  • 使用的地方不一样: @Component是在类上面用;@Bean是在方法上使用
  • 使用场景不一样:@Bean可以将无法修改源代码的类(第三方jar包中的类)交由IOC容器管理,而@Component注解只能用来标注我们自己写的类。
  • @Component注解使用起来更简单,@Bean需要自己去实现初始化过程;

使用@Bean定义的bean,名称默认就是方法名,可以通过@Qualifier注解改变默认名称

  • @Bean明确地指示了产生一个bean的方法,并且交给Spring容器管理
  • 它很明确地告诉被注释的方法,你给我产生一个Bean,然后交给Spring容器
  • 记住,@Bean就放在方法上

@Value

给类中的属性设置值。

// 设置常量值
@Value(“张三”)
private String sname;

// 读取外部properties文件中的jdbc.url key对应的值
@Value("${jdbc.url}")
private String url;

@Required

已过时, 可以使用@Autowired的required属性代替

自定义注解

package com.lanou.spring.myannotaion;

import org.springframework.stereotype.Component;

import java.lang.annotation.*;

@Target(ElementType.TYPE) //注解可以在什么场合下使用 TYPE代表只能在类上使用,TYPE变成METHOD代表只能在方法上使用
@Retention(RetentionPolicy.RUNTIME)//注解保留到什么时候
@Documented //是否生成文档
@Component //将bean交由IOC管理
public @interface MyComponent {
}


使用

package com.lanou.spring.bean;

import com.lanou.spring.myannotaion.MyComponent;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 皇上选佳丽
 */
@Scope(scopeName = "prototype") //指定作用域(相当于xml中bean的scope属性)
@Getter
@Setter
@MyComponent    //使用派生自@Component注解的自定义注解实现bean定义功能
public class King {
    @Value("李世民")
    private String name;

    @Autowired  //默认是按照类型(byType)
//    @Qualifier("girl") //此注解配合上面的自动注入注解(代表按照名称注入bean byName)
    @Resource   //这是JSR-250规范里的原生注解,Spring也支持用此注解实现自动注入
                // 此注解的工作原理:先按照byName模式去查找bean,如果没找到自动切成成byType模式
    private Girl girl;
}



Spring-AOP

AOP的概念、思想

面向切面编程:在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想

SpringAOP和Aspectj的区别

Aspectj是一个专门主打面向切面编程的框架,它使用一种特殊的语言(拓展自Java语言)来编写切面代码,后缀是.aj格式,并且需要专门的编译器将其编译成jvm可以运行的.class文件。

SpringAOP底层也是使用了Aspectj的方案,但在上层做了很多封装层面的工作,可以让开发人员直接使用Java语言来编写切面。并且由于是使用的时标准的Java语言,所以并不需要再额外安装一个专门的编译器。但是由于开发人员直接接触的时SpringAOP,那么凡是Spring中没有实现的那些AOP功能,我们就用不了了。这种情况下只能跟产品经理沟通或者去学习原生的Aspectj。

AOP的术语

切面

切面由切点和通知组成,它既包括了横切逻辑的定义,也包括了连接点的定义

pointcut切点

切点就是定义了通知被应用的位置

  • 要横切的点(在Spring中就是Pointcut,通常是一个表达式)
  • 切面与目标对象间的连接点有很多, 切点就是从众多的连接点中选择我们感兴趣的点将切面织入到目标代码中

所有的切点都来源于连接点,并不是所有的连接点都是切点

advice通知(要织入的代码)
前置通知(before)
  • 在目标方法被调用之前调用通知功能
  • 无法阻止目标方法执行
后置通知(after-returning)
  • 在目标方法正常执行之后调用通知,此时不会关心方法的输出是什么
  • 出现异常就无法通知
异常通知(after-throwing)

在目标方法抛出异常后调用通知

环绕通知(around)
  • 通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。
  • 可以阻止目标方法执行
  • 方法内部可以使用连接点对象获取被代理方法的所有信息:调用、屏蔽被代理方法
最终通知(after)

目标方法执行结束后通知,无论是否出现异常都可以执行,跟Finally相似

连接点
  • 连接点是一个比较空泛的概念,就是定义了哪一些地方是可以切入的,也就是所有允许你通知的地方。
  • 连接点是一个应用执行过程中能够插入一个切面的点。
  • 连接点可以是调用方法时、抛出异常时、甚至修改字段时
  • 切面代码可以利用这些点插入到应用的正规流程中
  • 程序执行过程中能够应用通知的所有点。
织入
  • 织入是将通知添加到目标类具体连接点上的过程。
  • 织入是将切面应用到目标对象来创建代理对象的过程。
  • 切面在指定的连接点被织入到目标对象中,在目标对象的生命周期中有多个点可以织入

Spring AOP的使用步骤

添加依赖包
<dependency>           
 <groupId>org.aspectj</groupId>        
 <artifactId>aspectjweaver</artifactId>
 <version>1.9.4</version>
</dependency>

XML方式
加入aop schema
<beans xmlns="http://www.springframework.org/schema/beans"
       <!--添加的-->
       xmlns:aop="http://www.springframework.org/schema/aop"
       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/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">

</beans>

定义切面类,并配置到applicationContext中

定义切面类

package com.lanou3g.spring.aop;

import org.aspectj.lang.ProceedingJoinPoint;

/**
 * 该切面用来插入起床的逻辑
 */
public class MyAspect {

    public void wakeup() {
        System.out.println("[前置通知]我刚学习SpringAOP睡着了,刚才谁打了我一下?");
    }


    public void goToBed() {
        System.out.println("[后置通知]SpringAOP太难了,一不小心又睡着了");
    }
}

配置到applicationContext中

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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/aop
       http://www.springframework.org/schema/beans/spring-aop.xsd">
	<!--将bean注入到spring容器中-->
    <bean id="Student" class="com.lanou3g.service.Student"/>
    <bean id="nr" class="com.lanou3g.service.NetRed"/>
    <bean id="coder" class="com.lanou3g.service.Coder"/>

    <!--将定义的切面类配置进来-->
   <bean id="wakeUpAspect"class="com.lanou3g.aop.MyAspect"/>
 </beans>

定义aop:config
引用切面bean
定义切入点表达式
定义通知
  • 通知类型:引用切入点表达式
  • 织入切面bean中的方法

上面三部曲的整合:

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

    <bean id="Student" class="com.lanou3g.service.Student"/>
    <bean id="nr" class="com.lanou3g.service.NetRed"/>
    <bean id="coder" class="com.lanou3g.service.Coder"/>

    <!--将定义的切面类配置进来-->
   <bean id="wakeUpAspect"class="com.lanou3g.aop.MyAspect"/>

    <aop:config>
        <!--相当于注解方式中定义了切入点-->
        <aop:pointcut id="beforeOneDay" expression="execution(* com.lanou3g..NetRed.oneDay(..))"/>
        <!--相当于注解方式中定义来了切面类-->
        <aop:aspect ref="wakeUpAspect">
            <!--前置通知-->
            <aop:before method="wakeup" pointcut-ref="beforeOneDay"/>
            <!--后置返回通知-->
            <aop:after-returning method="afterRetuing" pointcut-ref="beforeOneDay" returning="message"/>
            <!--环绕通知-->
            <aop:around method="aroundAdvice" pointcut-ref="beforeOneDay" />
            <!--后置异常通知-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="beforeOneDay" throwing="ex"/>
            <!--后置通知-->
            <aop:after method="goToBed" pointcut-ref="beforeOneDay"/>
        </aop:aspect>
    </aop:config>

 </beans>

注解方式

创建实体类,并注入到Spring中

package com.lanou3g.service;

import org.springframework.stereotype.Component;

@Component
public class Student{
    /**
     * AOP方式织入起床、睡觉
     */
    public String oneDay() {
//        System.out.println("1. 起床");
        System.out.println("2. 吃早饭");
        System.out.println("3. 进班学习");
        System.out.println("4. 吃中饭");
        System.out.println("5. 午休");
        System.out.println("6. 进班学习");
        System.out.println("7. 吃晚饭");
        System.out.println("8. 进班自习");
//        System.out.println("9. 睡觉");
        return "放学了!";
    }

}


package com.lanou3g.service;

import org.springframework.stereotype.Component;

/**
 * 程序员的一天
 */
@Component
public class Coder {
    /**
     * 用AOP思想解决:
     *      1. 需要有一个代理类来代理Coder
     *      2. 调用coder的oneDayByAOP方法时,实际上时通过代理来间接调用
     *      3. 在代理类调用真正的Coder中方法的过程中,可以动态插入一些其他的逻辑
     */
    public String oneDay() {
        System.out.println("2. 洗漱");
        System.out.println("3. 吃早饭");
        System.out.println("4. 挤地铁");
        System.out.println("5. 上班");
        System.out.println("6. 敲代码");
        System.out.println("7. 解Bug");
        System.out.println("8. 被领导骂");
        System.out.println("9. 加班");
        System.out.println("10. 又被骂");
        System.out.println("11. 删库跑路");
        return "下班了!";
    }
}


package com.lanou3g.service;

import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/**
 * 网红主播的一天
 */
@Component
public class NetRed {
    /**
     * 用AOP思想解决:
     *      1. 需要有一个代理类来代理Coder
     *      2. 调用coder的oneDayByAOP方法时,实际上时通过代理来间接调用
     *      3. 在代理类调用真正的Coder中方法的过程中,可以动态插入一些其他的逻辑
     */
    public String oneDay() {
        System.out.println("2. 开播");
        System.out.println("3. 开车");
        System.out.println("4. 表演节目");
        System.out.println("5. 开竞猜");

        /*String name = null;
        System.out.println(name.length());*/
        System.out.println("6. 主播PK");

        System.out.println("7. 被超管警告");
        System.out.println("8. 下播");


        return "网红的一天";
    }
}


开启自动织入支持
package com.lanou3g;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * 开启自动织入支持
 */
@Configuration //标识一个类作为Spring的一个bean配置文件
@ComponentScan(basePackages = "com.lanou3g")
@EnableAspectJAutoProxy // 开启注解支持,同时强制指定代理机制为cglib 
public class MyConfigauration {

}



定义切面类,添加@Aspect、@Component注解
  • 定义切入点(方法加注解)

    package com.lanou3g;
    
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    @Component
    /**
     * 定义切入点
     */
    public class MyPointCut {
        @Pointcut("execution(* oneDay(..))")
        public void allOneDayMethod(){
    
        }
    }
    
    
    
    

    或者把切入点定义到切面类中,如下

  • 定义切面类

    package com.lanou3g.aop;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;
    
    /**
     * 定义切面类
     */
    @Aspect
    /**
    *由于@Aspect注解没有让Spring作为组件bean扫描的能力,所以我们*需要额外添加@Component注解
    */
    @Component
    public class MyAspect {
        /**
        *定义切入点
        */
        @Pointcut("execution(* oneDay(..))")
        public void allOneDayMethod(){
    
        }
      	/**
      	*前置通知
      	*/
        @Before("allOneDayMethod()")
        public void wakeup() {
            System.out.println("[前置通知]我刚学习SpringAOP睡着了,刚才谁打了我一下?");
        }
    
       /**
      	*后置通知
      	*/ @After("com.lanou3g.MyPointCut.allOneDayMethod()")
        public void goToBed() {
            System.out.println("[后置通知]SpringAOP太难了,一不小心又睡着了");
        }
    	/**
      	*后置返回通知
      	*/
        @AfterReturning(value = "com.lanou3g.MyPointCut.allOneDayMethod()",returning = "message")
        public void afterRetuing(Object message) {
            System.out.println("[后置返回通知]方法执行已经return了,方法返回值是:" + message);
        }
    	/**
      	*后置异常通知
      	*/
        @AfterThrowing(value = "com.lanou3g.MyPointCut.allOneDayMethod()",throwing = "ex")
        public void afterThrowing(Throwable ex) {
            System.out.println("[后置异常通知]方法执行出现异常,异常原因:" + ex.getMessage());
        }
    
        /**
         * 环绕通知
         */
        @Around("com.lanou3g.MyPointCut.allOneDayMethod()")
        public void aroundAdvice(ProceedingJoinPoint joinPoint) {
    
            // 连接点参数可以获取到被切入方法的所有信息
            // 这里演示了如何获取被切入方法的名称
            String targetMethodName = joinPoint.getSignature().getName();
            System.out.println("[环绕通知]被切入的方法名:" + targetMethodName);
    
            //
            System.out.println("[环绕通知]即将开始新的一天, 早起的鸟儿有虫吃!");
            try {
                joinPoint.proceed();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            System.out.println("[环绕通知]这真是充实的一天, 早睡早起,方能养生!");
    
        }
    }
    
    
    
    
  • 定义通知(方法加注解)

    @AfterReturning(pointcut = "com.lanou3g.spring.GlobalPointcut.say_all_method()", returning = "ret")
        public Object afterRM(Object ret) {
            log.debug("[afterRM] 返回值: " + ret);
            return ret;
        }
    
    
    

Spring AOP的代理机制

JDK动态代理
  • 创建接口
package com.lanou3g.service;

public interface Man {
      String oneDay();
}




  • 让实体类继承接口并实现其方法
  package com.lanou3g.service;
  
  /**
   * 网红主播的一天
   */
  public class NetRed implements Man{
      /**
       * 使用JDK动态代理,动态在方法执行前和执行后添加一些操作
       */
      public String oneDay() {
  
          System.out.println("2. 开播");
          System.out.println("3. 开车");
          System.out.println("4. 表演节目");
          System.out.println("5. 开竞猜");
          System.out.println("6. 主播PK");
          System.out.println("7. 被超管警告");
          System.out.println("8. 下播");
          return "网红的一天";
      }
  }
  


  • 定义一个事件管理器类实现invocationHandle接口,并重写invoke(代理类,被代理的方法,方法的参数列表)方法。
  package com.lanou3g.jdkproxy;
  
  import java.lang.reflect.InvocationHandler;
  import java.lang.reflect.Method;
  
  /**
   * 此代理类负责在被代理类的方法运行前和后分别做一些操作
   */
  
  /**
   * JDK代理方式仅适于用实现了接口的类
   *
   * 因为JDK创建代理类的原理是, 先创建一个Object,然后让这个代理类实现指定的接口,进而拥有被代理类所有从接口中实现的方法
   */
  public class MethodBeforeAfterProxy implements InvocationHandler {
      Object target;
      public MethodBeforeAfterProxy(Object target){
          this.target = target;
      }
     /** 
     * 参数: 
     *methodProxy 被代理的对象 
     *method 被代理对象的方法 
     *args 方法的参数  
     *target 方法返回值 
     */
      @Override
      public Object invoke(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
          String methodName = method.getName();
          //模拟在方法运行前执行的操作
          System.out.println(methodName + "方法开始执行了");
          Object invoke = method.invoke(target, args);
          //模拟方法在运行后执行的操作
          System.out.println(methodName + "方法执行结束了" + invoke);
          return invoke;
      }
  }
  


  • 调用Proxy.newProxyInstance(类加载器,类实现的接口,事务处理器对象)生成一个代理实例。通过该代理实例调用方法
  public static void testJDkDynamicProxy() {
          Man netRed = new NetRed();
  
          MethodBeforeAfterProxy mba = new MethodBeforeAfterProxy(netRed);
          Man netRedProxy = (Man) Proxy.newProxyInstance(MethodBeforeAfterProxy.class.getClassLoader(), new Class[]{Man.class}, mba);
          netRedProxy.oneDay();
      }


动态代理不需要我们去编写代理类,是在程序中动态生成的。

CGLIB动态代理

Cglib可以代理实现接口的类、也可以代理未实现接口的类

代理实现接口的类
  • 定义接口
  package com.lanou3g.service2;
  
  public interface Animal {
      /**
       * 动物吼叫
       */
      void bray();
  }
  
  


  • 实现接口的类
  package com.lanou3g.service2;
  
  public class Cat implements Animal {
      public void bray() {
          System.out.println("喵喵~");
      }
  }


  • 在pom文件中添加依赖
  <dependency>
       <groupId>cglib</groupId>
       <artifactId>cglib</artifactId>
       <version>3.2.5</version>
  </dependency>


  • 生成代理类,实现MethodInterceptor接口,并重写intercept方法
  package com.lanou3g.cglibproxy;
  
  import net.sf.cglib.proxy.Enhancer;
  import net.sf.cglib.proxy.MethodInterceptor;
  import net.sf.cglib.proxy.MethodProxy;
  import java.lang.reflect.Method;
  
  public class MyCglibProxy implements MethodInterceptor {
      private Enhancer enhancer = new Enhancer();
  
      public Object getProxy(Class clazz) {
          enhancer.setSuperclass(clazz);
          enhancer.setCallback(this);
          enhancer.setUseCache(false);
          return enhancer.create();
      }
  
       /** 
       * 拦截所有目标类方法的调用 
       * 参数: 
       * target  目标实例对象 
       * method 目标方法的反射对象 
       * args 方法的参数 
       * methodProxy 代理类的实例 
       */
      @Override
      public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
          String methodName = method.getName();
          System.out.println(methodName + "开始执行了");
          //代理类对象实例调用父类方法
          Object retVal = methodProxy.invokeSuper(target, args);
          System.out.println(methodName + "执行结束了");
          return retVal;
      }
  }
  


  • 调用cglibProxy.getProxy生成一个实例,使用该实例
       /**
       * cglib动态代理
       * Cglib可以代理实现接口的类、也可以代理未实现接口的类
       */
      public static void testCglibProxy() {
          MyCglibProxy cglibProxy = new MyCglibProxy();
          Cat cat = (Cat) cglibProxy.getProxy(Cat.class);
          cat.bray();
      }


代理未实现接口的类
  • 定义一个类
  package com.lanou3g.proxy.service2;
  public class Cat {
      public void bray() {
          System.out.println("喵喵~");
      }
  }
  


  • 在pom文件中添加依赖
  • 生成代理类,实现MethodInterceptor接口,并重写intercept方法
  • 调用cglibProxy.getProxy生成一个实例,使用该实例

步骤同上

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一部分 Spring framework 概述..5 第1 章 Spring Framework 介绍..6 1.1 依赖注入和控制反转.6 1.2 模块6 1.2.1 核心容器.7 1.2.2 数据访问/ 整合..7 1.2.3 Web ..8 1.2.4 AOP 和设备组件.8 1.2.5 测试.8 1.3 使用方案8 1.3.1 依赖管理和命名规约.. 12 1.3.1.1 Spring 依赖和基于Spring 13 1.3.1.2 Maven 依赖管理. 14 1.3.1.3 Ivy 依赖管理 15 1.3.2 日志. 16 1.3.2.1 不使用Commons Logging .. 17 1.3.2.2 使用SLF4J 17 1.3.2.3 使用Log4J .. 19 第二部分 Spring 3 的新特性.. 21 第2 章 Spring 3.0 的新特性和增强 21 2.1 Java 5.. 21 2.2 改进的文档. 21 2.3 新的文章和教程. 21 2.4 新的模块组织方式和构建系统.. 22 2.5 新特性概述. 22 2.5.1 为Java 5 更新的核心API .. 23 2.5.2 Spring 表达式语言 23 2.5.3 控制反转(IoC)容器. 24 2.5.3.1 基于Java 的bean 元数据.. 24 2.5.3.2 使用组件定义bean 的元数据 25 2.5.4 通用的类型转换系统和字段格式化系统 25 2.5.5 数据层.. 25 2.5.6 Web 层 25 2.5.6.1 全面的REST 支持. 26 2.5.6.2 @MVC 的增加 26 2.5.7 声明式的模型验证. 26 2.5.8 先期对Java EE 6 的支持. 26 2.5.9 嵌入式数据库的支持.. 26 第3 章 Spring 3.1 的新特性和增强 27 3.1 新特性概述. 27 第三部分 核心技术 28 ----------------------- Page 3----------------------- 第4 章 IoC 容器.. 29 4.1 Spring IoC 容器和bean 的介绍 29 4.2 容器概述 29 4.2.1 配置元数据.. 30 4.2.2 实例化容器.. 31 4.2.2.1 处理基于XML 的配置元数据. 32 4.2.3 使用容器. 33 4.3 Bean 概述 34 4.3.1 命名bean .. 34 4.3.1.1 在bean 定义外面起别名 35 4.3.2 实例化bean . 36 4.3.2.1 使用构造方法实例化 36 4.3.2.2 使用静态工厂方法来实例化.. 36 4.3.2.3 使用实例工厂方法来实例化.. 37 4.4 依赖 38 4.4.1 依赖注入. 38 4.4.1.1 基于构造方法的依赖注入 39 4.4.1.2 基于setter 方法的依赖注入 41 4.4.1.3 解决依赖过程.. 42 4.4.1.4 依赖注入示例.. 43 4.4.2 深入依赖和配置.. 45 4.4.2.1 直接值(原生类型,String,等). 45 4.4.2.2 引用其它bean (协作者).. 47 4.4.2.3 内部bean 48 4.4.2.4 集合.. 48 4.4.2.5 null 和空字符串 51 4.4.2.6 使用p-命名空间的XML 快捷方式 52 4.4.2.7 使用c-命名空间的XML 快捷方式. 53 4.4.2.8 复合属性名称.. 54 4.4.3 使用depends-on 54 4.4.4 延迟初始化bean . 55 4.4.5 自动装配协作者.. 55 4.4.5.1 自动装配的限制和缺点.. 56 4.4.5.2 从自动装配中排除bean. 57 4.4.6 方法注入. 57 4.4.6.1 查找方法注入.. 58 4.4.6.2 任意方法的替代 59 4.5 Bean 的范围. 60 4.5.1 单例范围. 61 4.5.2 原型范围. 62 4.5.3 单例bean 和原型bean 依赖. 63 4.5.4 请求,会话和全局会话范围. 63 4.5.4.1 初始化Web 配置.. 63 4.5.4.2 请求范围.. 64 ----------------------- Page 4----------------------- 4.5.4.3 会话范围.. 64 4.5.4.4 全局会话范围.. 65 4.5.4.5 各种范围的bean 作为依赖. 65 4.5.5 自定义范围.. 67 4.5.5.1 创建自定义范围 67 4.5.5.2 使用自定义范围 68 4.6 自定义bean 的性质. 69 4.6.1 生命周期回调. 69 4.6.1.1 初始化回调 70 4.6.1.2 销毁回调.. 70 4.6.1.3 默认的初始化和销毁方法 71 4.6.1.4 组合生命周期机制.. 72 4.6.1.5 启动和关闭回调 73 4.6.1.6 在非Web 应用中,优雅地关闭Spring IoC 容器 74 4.6.2 ApplicationContextAware 和BeanNameAware . 75 4.6.3 其它Aware 接口 75 4.7 Bean 定义的继承. 77 4.8 容器扩展点. 78 4.8.1 使用BeanPostProcessor 来自定义bean 78 4.8.1.1 示例:BeanPostProcessor 风格的Hello World.. 79 4.8.1.2 示例:RequiredAnnotationBeanPostProcessor 81 4.8.2 使用BeanFactoryPostProcessor 自定义配置元数据. 81 4.8.2.1 示例:PropertyPlaceholderConfigurer. 82 4.8.2.2 示例:PropertyOverrideConfigurer 83 4.8.3 使用FactoryBean 来自定义实例化逻辑. 84 4.9 基于注解的容器配置. 85 4.9.1 @Required.. 86 4.9.2 @Autowired和@Inject.. 86 4.9.3 使用限定符来微调基于注解的自动装配 89 4.9.4 CustomAutowireConfigurer. 94 4.9.5 @Resource.. 95 4.9.6 @PostConstruct和@PreDestroy . 96 4.10 类路径扫描和管理的组件.. 96 4.10.1 @Component和更多典型注解 97 4.10.2 自动检测类和bean 的注册. 97 4.10.3 使用过滤器来自定义扫描 98 4.10.4 使用组件定义bean 的元数据.. 99 4.10.5 命名自动检测组件 100 4.10.6 为自动检测组件提供范围. 101 4.10.7 使用注解提供限定符元数据. 102
2.1. 简介 2.2. 控制反转(IoC)容器 2.2.1. 新的bean作用域 2.2.2. 更简单的XML配置 2.2.3. 可扩展的XML编写 2.2.4. Annotation(注解)驱动配置 2.2.5. 在classpath中自动搜索组件 2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@AspectJ 切面的支持 2.3.3. 对bean命名pointcut( bean name pointcut element)的支持 2.3.4. 对AspectJ装载时织入(AspectJ load-time weaving)的支持 2.4. 中间层 2.4.1. 在XML里更为简单的声明性事务配置 2.4.2. 对Websphere 事务管理的完整支持 2.4.3. JPA 2.4.4. 异步的JMS 2.4.5. JDBC 2.5. Web层 2.5.1. Spring MVC合理的默认值 2.5.2. Portlet 框架 2.5.3. 基于Annotation的控制器 2.5.4. Spring MVC的表单标签库 2.5.5. 对Tiles 2 支持 2.5.6. 对JSF 1.2支持 2.5.7. JAX-WS支持 2.6. 其他 2.6.1. 动态语言支持 2.6.2. 增强的测试支持 2.6.3. JMX 支持 2.6.4. 将Spring 应用程序上下文部署为JCA adapter 2.6.5. 计划任务 2.6.6. 对Java 5 (Tiger) 支持 2.7. 移植到Spring 2.5 2.7.1. 改变 2.8. 更新的样例应用 2.9. 改进的文档 I. 核心技术 3. IoC(控制反转)容器 3.1. 简介 3.2. 基本原理 - 容器和bean 3.2.1. 容器 3.2.2. 实例化容器 3.2.3. 多种bean 3.2.4. 使用容器 3.3. 依赖 3.3.1. 注入依赖 3.3.2. 依赖配置详解 3.3.3. 使用depends-on 3.3.4. 延迟初始化bean 3.3.5. 自动装配(autowire)协作者 3.3.6. 依赖检查 3.3.7. 方法注入 3.4. Bean的作用域 3.4.1. Singleton作用域 3.4.2. Prototype作用域 3.4.3. Singleton beans和prototype-bean的依赖 3.4.4. 其他作用域 3.4.5. 自定义作用域 3.5. 定制bean特性 3.5.1. 生命周期回调 3.5.2. 了解自己 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. The ApplicationContext 3.8.1. BeanFactory 还是 ApplicationContext? 3.8.2. 利用MessageSource实现国际化 3.8.3. 事件 3.8.4. 底层资源的访问 3.8.5. ApplicationContext在WEB应用中的实例化 3.9. 粘合代码和可怕的singleton 3.10. 以J2EE RAR文件的形式部署Spring ApplicationContext 3.11. 基于注解(Annotation-based)的配置 3.11.1. @Autowired 3.11.2. 基于注解的自动连接微调 3.11.3. CustomAutowireConfigurer 3.11.4. @Resource 3.11.5. @PostConstruct 与 @PreDestroy 3.12. 对受管组件的Classpath扫描 3.12.1. @Component和更多典型化注解 3.12.2. 自动检测组件 3.12.3. 使用过滤器自定义扫描 3.12.4. 自动检测组件的命名 3.12.5. 为自动检测的组件提供一个作用域 3.12.6. 用注解提供限定符元数据 3.13. 注册一个LoadTimeWeaver 4. 资源 4.1. 简介 4.2. Resource接口 4.3. 内置 Resource 实现 4.3.1. UrlResource 4.3.2. ClassPathResource 4.3.3. FileSystemResource 4.3.4. ServletContextResource 4.3.5. InputStreamResource 4.3.6. ByteArrayResource 4.4. ResourceLoader接口 4.5. ResourceLoaderAware 接口 4.6. 把Resource作为属性来配置 4.7. Application context 和Resource 路径 4.7.1. 构造application context 4.7.2. Application context构造器中资源路径的通配符 4.7.3. FileSystemResource 说明 5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到错误信息 5.4. Bean处理和BeanWrapper 5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建的PropertyEditor实现 6. 使用Spring进行面向切面编程(AOP) 6.1. 简介 6.1.1. AOP概念 6.1.2. Spring AOP的功能和目标 6.1.3. AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个切入点(pointcut) 6.2.4. 声明通知 6.2.5. 引入(Introduction) 6.2.6. 切面实例化模型 6.2.7. 例子 6.3. 基于Schema的AOP支持 6.3.1. 声明一个切面 6.3.2. 声明一个切入点 6.3.3. 声明通知 6.3.4. 引入 6.3.5. 切面实例化模型 6.3.6. Advisor 6.3.7. 例子 6.4. AOP声明风格的选择 6.4.1. Spring AOP还是完全用AspectJ? 6.4.2. Spring AOP中使用@AspectJ还是XML? 6.5. 混合切面类型 6.6. 代理机制 6.6.1. 理解AOP代理 6.7. 以编程方式创建@AspectJ代理 6.8. 在Spring应用中使用AspectJ 6.8.1. 在Spring中使用AspectJ进行domain object的依赖注入 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用中使用AspectJ加载时织入(LTW) 6.9. 更多资源 7. Spring AOP APIs 7.1. 简介 7.2. Spring中的切入点API 7.2.1. 概念 7.2.2. 切入点运算 7.2.3. AspectJ切入点表达式 7.2.4. 便利的切入点实现 7.2.5. 切入点的超类 7.2.6. 自定义切入点 7.3. Spring的通知API 7.3.1. 通知的生命周期 7.3.2. Spring里的通知类型 7.4. Spring里的Advisor API 7.5. 使用ProxyFactoryBean创建AOP代理 7.5.1. 基础 7.5.2. JavaBean属性 7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对接口进行代理 7.5.5. 对类进行代理 7.5.6. 使用“全局”通知器 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动代理(autoproxy)”功能 7.9.1. 自动代理bean定义 7.9.2. 使用元数据驱动的自动代理 7.10. 使用TargetSource 7.10.1. 热交换目标源 7.10.2. 池化目标源 7.10.3. 原型目标源 7.10.4. ThreadLocal目标源 7.11. 定义新的Advice类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.2.1. Mock对象 8.2.2. 单元测试支持类 8.3. 集成测试 8.3.1. 概览 8.3.2. 使用哪个支持框架 8.3.3. 通用目标 8.3.4. JDBC测试支持 8.3.5. 常用注解 8.3.6. JUnit 3.8遗留支持 8.3.7. Spring TestContext Framework 8.3.8. PetClinic示例 8.4. 更多资源 II. 中间层数据访问 9. 事务管理 9.1. 简介 9.2. 动机 9.3. 关键抽象 9.4. 使用资源同步的事务 9.4.1. 高层次方案 9.4.2. 低层次方案 9.4.3. TransactionAwareDataSourceProxy 9.5. 声明式事务管理 9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 事务传播 9.5.8. 通知事务操作 9.5.9. 结合AspectJ使用 @Transactional 9.6. 编程式事务管理 9.6.1. 使用TransactionTemplate 9.6.2. 使用PlatformTransactionManager 9.7. 选择编程式事务管理还是声明式事务管理 9.8. 与特定应用服务器集成 9.8.1. IBM WebSphere 9.8.2. BEA WebLogic 9.8.3. Oracle OC4J 9.9. 常见问题的解决方法 9.9.1. 对一个特定的 DataSource 使用了错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 11.1.1. 选择一种工作模式 11.1.2. Spring JDBC包结构 11.2. 利用JDBC核心类控制JDBC的基本操作和错误处理 11.2.1. JdbcTemplate类 11.2.2. NamedParameterJdbcTemplate类 11.2.3. SimpleJdbcTemplate类 11.2.4. DataSource接口 11.2.5. SQLExceptionTranslator接口 11.2.6. 执行SQL语句 11.2.7. 执行查询 11.2.8. 更新数据库 11.2.9. 获取自动生成的主键 11.3. 控制数据库连接 11.3.1. DataSourceUtils类 11.3.2. SmartDataSource接口 11.3.3. AbstractDataSource类 11.3.4. SingleConnectionDataSource类 11.3.5. DriverManagerDataSource类 11.3.6. TransactionAwareDataSourceProxy类 11.3.7. DataSourceTransactionManager类 11.3.8. NativeJdbcExtractor 11.4. JDBC批量操作 11.4.1. 使用JdbcTemplate进行批量操作 11.4.2. 使用SimpleJdbcTemplate进行批量操作 11.5. 通过使用SimpleJdbc类简化JDBC操作 11.5.1. 使用SimpleJdbcInsert插入数据 11.5.2. 使用SimpleJdbcInsert来获取自动生成的主键 11.5.3. 指定SimpleJdbcInsert所使用的字段 11.5.4. 使用SqlParameterSource提供参数值 11.5.5. 使用SimpleJdbcCall调用存储过程 11.5.6. 声明SimpleJdbcCall使用的参数 11.5.7. 如何定义SqlParameters 11.5.8. 使用SimpleJdbcCall调用内置函数 11.5.9. 使用SimpleJdbcCall返回的ResultSet/REF Cursor 11.6. 用Java对象来表达JDBC操作 11.6.1. SqlQuery类 11.6.2. MappingSqlQuery类 11.6.3. SqlUpdate类 11.6.4. StoredProcedure类 11.6.5. SqlFunction类 11.7. 参数和数据处理的基本原则 11.7.1. 为参数设置SQL类型信息 11.7.2. 处理BLOB 和 CLOB对象 11.7.3. 在IN语句中传入一组参数值 11.7.4. 处理复杂类型的存储过程调用 12. 使用ORM工具进行数据访问 12.1. 简介 12.2. Hibernate 12.2.1. 资源管理 12.2.2. 在Spring容器中创建 SessionFactory 12.2.3. The HibernateTemplate 12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用服务器中使用Hibernate的注意事项 12.3. JDO 12.3.1. 建立PersistenceManagerFactory 12.3.2. JdoTemplate和JdoDaoSupport 12.3.3. 基于原生的JDO API实现DAO 12.3.4. 事务管理 12.3.5. JdoDialect 12.4. Oracle TopLink 12.4.1. SessionFactory 抽象层 12.4.2. TopLinkTemplate and TopLinkDaoSupport 12.4.3. 基于原生的TopLink API的DAO实现 12.4.4. 事务管理 12.5. iBATIS SQL Maps 12.5.1. 创建SqlMapClient 12.5.2. 使用 SqlMapClientTemplate 和 SqlMapClientDaoSupport 12.5.3. 基于原生的iBATIS API的DAO实现 12.6. JPA 12.6.1. 在Spring环境中建立JPA 12.6.2. JpaTemplate 和 JpaDaoSupport 12.6.3. 基于原生的JPA实现DAO 12.6.4. 异常转化 12.7. 事务管理 12.8. JpaDialect III. The Web 13. Web MVC framework Web框架 13.1. 概述 13.1.1. 与其他MVC实现框架的集成 13.1.2. Spring Web MVC框架的特点 13.2. DispatcherServlet 13.3. 控制器 13.3.1. AbstractController 和 WebContentGenerator 13.3.2. 其它的简单控制器 13.3.3. MultiActionController 13.3.4. 命令控制器 13.4. 处理器映射(handler mapping) 13.4.1. BeanNameUrlHandlerMapping 13.4.2. SimpleUrlHandlerMapping 13.4.3. 拦截器(HandlerInterceptor) 13.5. 视图与视图解析 13.5.1. 视图解析器(ViewResolver) 13.5.2. 视图解析链 13.5.3. 重定向(Rediret)到另一个视图 13.6. 本地化解析器 13.6.1. AcceptHeaderLocaleResolver 13.6.2. CookieLocaleResolver 13.6.3. SessionLocaleResolver 13.6.4. LocaleChangeInterceptor 13.7. 使用主题 13.7.1. 简介 13.7.2. 如何定义主题 13.7.3. 主题解析器 13.8. Spring对分段文件上传(multipart file upload)的支持 13.8.1. 介绍 13.8.2. 使用MultipartResolver 13.8.3. 在表单中处理分段文件上传 13.9. 使用Spring的表单标签库 13.9.1. 配置 13.9.2. form标签 13.9.3. input标签 13.9.4. checkbox标签 13.9.5. checkboxes标签 13.9.6. radiobutton标签 13.9.7. radiobuttons标签 13.9.8. password标签 13.9.9. select标签 13.9.10. option标签 13.9.11. options标签 13.9.12. textarea标签 13.9.13. hidden标签 13.9.14. errors标签 13.10. 处理异常 13.11. 惯例优先原则(convention over configuration) 13.11.1. 对控制器的支持:ControllerClassNameHandlerMapping 13.11.2. 对模型的支持:ModelMap(ModelAndView) 13.11.3. 对视图的支持:RequestToViewNameTranslator 13.12. 基于注解的控制器配置 13.12.1. 建立dispatcher实现注解支持 13.12.2. 使用@Controller定义一个控制器 13.12.3. 使用@RequestMapping映射请求 13.12.4. 使用@RequestParam绑定请求参数到方法参数 13.12.5. 使用@ModelAttribute提供一个从模型到数据的链接 13.12.6. 使用@SessionAttributes指定存储在会话中的属性 13.12.7. 自定义WebDataBinder初始化 13.13. 更多资源 14. 集成视图技术 14.1. 简介 14.2. JSP和JSTL 14.2.1. 视图解析器 14.2.2. 'Plain-old' JSPs versus JSTL 'Plain-old' JSP与JSTL 14.2.3. 帮助简化开发的额外的标签 14.3. Tiles 14.3.1. 需要的资源 14.3.2. 如何集成Tiles 14.4. Velocity和FreeMarker 14.4.1. 需要的资源 14.4.2. Context 配置 14.4.3. 创建模板 14.4.4. 高级配置 14.4.5. 绑定支持和表单处理 14.5. XSLT 14.5.1. 写在段首 14.5.2. 小结 14.6. 文档视图(PDF/Excel) 14.6.1. 简介 14.6.2. 配置和安装 14.7. JasperReports 14.7.1. 依赖的资源 14.7.2. 配置 14.7.3. 构造ModelAndView 14.7.4. 使用子报表 14.7.5. 配置Exporter的参数 15. 集成其它Web框架 15.1. 简介 15.2. 通用配置 15.3. JavaServer Faces 15.3.1. DelegatingVariableResolver 15.3.2. FacesContextUtils 15.4. Struts 15.4.1. ContextLoaderPlugin 15.4.2. ActionSupport Classes 15.5. Tapestry 15.5.1. 注入 Spring 托管的 beans 15.6. WebWork 15.7. 更多资源 16. Portlet MVC框架 16.1. 介绍 16.1.1. 控制器 - MVC中的C 16.1.2. 视图 - MVC中的V 16.1.3. Web作用范围的Bean 16.2. DispatcherPortlet 16.3. ViewRendererServlet 16.4. 控制器 16.4.1. AbstractController 和 PortletContentGenerator 16.4.2. 其它简单的控制器 16.4.3. Command控制器 16.4.4. PortletWrappingController 16.5. 处理器映射 16.5.1. PortletModeHandlerMapping 16.5.2. ParameterHandlerMapping 16.5.3. PortletModeParameterHandlerMapping 16.5.4. 增加 HandlerInterceptors 16.5.5. HandlerInterceptorAdapter 16.5.6. ParameterMappingInterceptor 16.6. 视图和它们的解析 16.7. Multipart文件上传支持 16.7.1. 使用 PortletMultipartResolver 16.7.2. 处理表单里的文件上传 16.8. 异常处理 16.9. Portlet应用的部署 IV. 整合 17. 使用Spring进行远程访问与Web服务 17.1. 简介 17.2. 使用RMI暴露服务 17.2.1. 使用RmiServiceExporter暴露服务 17.2.2. 在客户端链接服务 17.3. 使用Hessian或者Burlap通过HTTP远程调用服务 17.3.1. 为Hessian和co.配置DispatcherServlet 17.3.2. 使用HessianServiceExporter暴露你的bean 17.3.3. 在客户端连接服务 17.3.4. 使用Burlap 17.3.5. 对通过Hessian或Burlap暴露的服务使用HTTP Basic认证 17.4. 使用HTTP调用器暴露服务 17.4.1. Exposing the service object 17.4.2. 在客户端连接服务 17.5. Web Services 17.5.1. 使用JAX-RPC暴露基于servlet的web服务 17.5.2. 使用JAX-RPC访问web服务 17.5.3. 注册JAX-RPC Bean映射 17.5.4. 注册自己的JAX-RPC 处理器 17.5.5. 使用JAX-WS暴露基于servlet的web服务 17.5.6. 使用JAX-WS暴露单独web服务 17.5.7. 使用Spring支持的JAX-WS RI来暴露服务 17.5.8. 使用JAX-WS访问web服务 17.5.9. 使用XFire来暴露Web服务 17.6. JMS 17.6.1. 服务端配置 17.6.2. 客户端配置 17.7. 对远程接口不提供自动探测实现 17.8. 在选择这些技术时的一些考虑 18. Enterprise Java Beans (EJB) 集成 18.1. 简介 18.2. 访问EJB 18.2.1. 概念 18.2.2. 访问本地的无状态Session Bean(SLSB) 18.2.3. 访问远程SLSB 18.2.4. Accessing EJB 2.x SLSBs versus EJB 3 SLSBs 18.3. 使用Spring提供的辅助类实现EJB组件 18.3.1. EJB 2.x base classes 18.3.2. EJB 3 注入拦截 19. JMS (Java Message Service) 19.1. 简介 19.2. 使用Spring JMS 19.2.1. JmsTemplate 19.2.2. 连接工厂 19.2.3. 目的地管理 19.2.4. 消息侦听容器 19.2.5. 事务管理 19.3. 发送消息 19.3.1. 使用消息转换器 19.3.2. SessionCallback 和 ProducerCallback 19.4. 接收消息 19.4.1. 同步接收 19.4.2. 异步接收 - 消息驱动的POJO 19.4.3. SessionAwareMessageListener接口 19.4.4. MessageListenerAdapter 19.4.5. 事务中的消息处理 19.5. JCA消息端点的支持 19.6. JMS命名空间支持 20. JMX 20.1. 介绍 20.2. 将Bean暴露为JMX 20.2.1. 创建MBeanServer 20.2.2. 重用原有的MBeanServer 20.2.3. 延迟初始化的MBean 20.2.4. MBean的自动注册 20.2.5. 控制注册行为 20.3. 控制Bean的管理接口 20.3.1. MBeanInfoAssembler接口 20.3.2. 使用源码级元数据 20.3.3. 使用JDK 5.0的注解 20.3.4. 源代码级的元数据类型 20.3.5. AutodetectCapableMBeanInfoAssembler接口 20.3.6. 用Java接口定义管理接口 20.3.7. 使用MethodNameBasedMBeanInfoAssembler 20.4. 控制Bean的ObjectName 20.4.1. 从Properties读取Properties 20.4.2. 使用MetadataNamingStrategy 20.4.3. 元素 20.5. JSR-160连接器 20.5.1. 服务器端连接器 20.5.2. 客户端连接器 20.5.3. 基于Burlap/Hessian/SOAP的JMX 20.6. 通过代理访问MBean 20.7. 通知 20.7.1. 为通知注册监听器 20.7.2. 发布通知 20.8. 更多资源 21. JCA CCI 21.1. 简介 21.2. 配置CCI 21.2.1. 连接器配置 21.2.2. 在Spring中配置ConnectionFactory 21.2.3. 配置CCI连接 21.2.4. 使用一个 CCI 单连接 21.3. 使用Spring的 CCI访问支持 21.3.1. 记录转换 21.3.2. CciTemplate类 21.3.3. DAO支持 21.3.4. 自动输出记录生成 21.3.5. 总结 21.3.6. 直接使用一个CCI Connection接口和Interaction接口 21.3.7. CciTemplate 使用示例 21.4. 建模CCI访问为操作对象 21.4.1. MappingRecordOperation 21.4.2. MappingCommAreaOperation 21.4.3. 自动生成输出记录 21.4.4. 总结 21.4.5. MappingRecordOperation 使用示例 21.4.6. MappingCommAreaOperation 使用示例 21.5. 事务 22. Spring邮件抽象层 22.1. 简介 22.2. 使用Spring邮件抽象 22.2.1. MailSender 和 SimpleMailMessage 的基本用法 22.2.2. 使用 JavaMailSender 和 MimeMessagePreparator 22.3. 使用MimeMessageHelper 22.3.1. 发送附件和嵌入式资源(inline resources) 22.3.2. 使用模板来创建邮件内容 23. Spring中的定时调度(Scheduling)和线程池(Thread Pooling) 23.1. 简介 23.2. 使用OpenSymphony Quartz 调度器 23.2.1. 使用JobDetailBean 23.2.2. 使用 MethodInvokingJobDetailFactoryBean 23.2.3. 使用triggers和SchedulerFactoryBean来包装任务 23.3. 使用JDK Timer支持类 23.3.1. 创建定制的timers 23.3.2. 使用 MethodInvokingTimerTaskFactoryBean类 23.3.3. 最后:使用TimerFactoryBean来设置任务 23.4. SpringTaskExecutor抽象 23.4.1. TaskExecutor接口 23.4.2. TaskExecutor类型 23.4.3. 使用TaskExecutor 24. 动态语言支持 24.1. 介绍 24.2. 第一个示例 24.3. 定义动态语言支持的bean 24.3.1. 公共概念 24.3.2. JRuby beans 24.3.3. Groovy beans 24.3.4. BeanShell beans 24.4. 场景 24.4.1. Spring MVC控制器的脚本化 24.4.2. Validator的脚本化 24.5. Bits and bobs 24.5.1. AOP - 通知脚本化bean 24.5.2. 作用域 24.6. 更多的资源 25. 注解和源代码级的元数据支持 25.1. 简介 25.2. Spring的元数据支持 25.3. 注解 25.3.1. @Required 25.3.2. Spring中的其它@Annotations 25.4. Jakarta Commons Attributes集成 25.5. 元数据和Spring AOP自动代理 25.5.1. 基本原理 25.5.2. 声明式事务管理 V. 示例程序 26. 演示案例 26.1. 介绍 26.2. 使用动态语言实现的Spring MVC控制器 26.2.1. 构建与部署 26.3. 使用SimpleJdbcTemplate和@Repository实现DAO 26.3.1. 域对象 26.3.2. Data Access Object 26.3.3. 构建 A. XML Schema-based configuration A.1. Introduction A.2. XML Schema-based configuration A.2.1. Referencing the schemas A.2.2. The util schema A.2.3. The jee schema A.2.4. The lang schema A.2.5. The jms schema A.2.6. The tx (transaction) schema A.2.7. The aop schema A.2.8. The context schema A.2.9. The tool schema A.2.10. The beans schema A.3. Setting up your IDE A.3.1. Setting up Eclipse A.3.2. Setting up IntelliJ IDEA A.3.3. Integration issues B. Extensible XML authoring B.1. Introduction B.2. Authoring the schema B.3. Coding a NamespaceHandler B.4. Coding a BeanDefinitionParser B.5. Registering the handler and the schema B.5.1. 'META-INF/spring.handlers' B.5.2. 'META-INF/spring.schemas' B.6. Using a custom extension in your Spring XML configuration B.7. Meatier examples B.7.1. Nesting custom tags within custom tags B.7.2. Custom attributes on 'normal' elements B.8. Further Resources C. spring-beans-2.0.dtd D. spring.tld D.1. Introduction D.2. The bind tag D.3. The escapeBody tag D.4. The hasBindErrors tag D.5. The htmlEscape tag D.6. The message tag D.7. The nestedPath tag D.8. The theme tag D.9. The transform tag E. spring-form.tld E.1. Introduction E.2. The checkbox tag E.3. The checkboxes tag E.4. The errors tag E.5. The form tag E.6. The hidden tag E.7. The input tag E.8. The label tag E.9. The option tag E.10. The options tag E.11. The password tag E.12. The radiobutton tag E.13. The radiobuttons tag E.14. The select tag E.15. The textarea tag F. Spring 2.5开发手册中文化项目 F.1. 声明 F.2. 致谢 F.3. 参与人员 F.4. 项目历程 表格清单 3.1. bean定义 3.2. Autowiring modes 3.3. 依赖检查方式 3.4. Bean作用域 3.5. Feature Matrix特性表 3.6. 内置事件 3.7. 过滤器类型 4.1. Resource strings 5.1. 属性示例 5.2. 内建的PropertyEditors 6.1. DefaultContextLoadTimeWeaver LoadTimeWeaversDefaultContextLoadTimeWeaver类和LoadTimeWeavers接口 6.2. aspectj-weaving属性值 9.1. 有关的设置 9.2. 设置 9.3. @Transactional 注解的属性 13.1. WebApplicationContext中特殊的bean 13.2. DispatcherServlet初始化参数 13.3. AbstractController提供的功能 13.4. 视图解析器 13.5. CookieLocaleResolver的属性 13.6. ThemeResolver的实现 14.1. 宏定义表 14.2. JasperReports View Classes 14.3. JasperReportsMultiFormatView默认Mapping Key映射 16.1. WebApplicationContext中特殊的Bean 16.2. DispatcherPortlet 的初始化参数 16.3. AbstractController提供的功能 19.1. JMS listener 元素的属性 19.2. JMS 元素的属性 19.3. JMS 元素的属性 20.1. 注册行为 20.2. 源代码级的元数据类型 20.3. 源代码级的元数据参数 21.1. Usage of Interaction execute methods 21.2. Usage of Interaction execute methods A.1. Eclipse XML editors D.1. Attributes D.2. Attributes D.3. Attributes D.4. Attributes D.5. Attributes D.6. Attributes D.7. Attributes D.8. Attributes E.1. Attributes E.2. Attributes E.3. Attributes E.4. Attributes E.5. Attributes E.6. Attributes E.7. Attributes E.8. Attributes E.9. Attributes E.10. Attributes E.11. Attributes E.12. Attributes E.13. Attributes E.14. Attributes

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值