Spring学习笔记

简介

  • Spring makes it easy to create Java enterprise applications。
  • 非入侵式
  • 设计理念。官方文档

IOC

类构造后再定义其属性(objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method)。

  • BeanFactory配置类。
    BeanFactory相关类
  • 创建bean
    • 编写类并在spring中注册
      <!--
          ref:引用另一个bean
          value:赋值
      -->
      <bean id="hello" class="com.ma.pojo.Hello">
          <property name="str" value="spring"/>
      </bean>
    
    • 获取springspring中注册的类
      ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
      Hello hello =(Hello) context.getBean("hello");
    
  • 编写多个spring配置文件,使用import引入
<beans>
    <import resource="services.xml"/>
    <import resource="resources/messageSource.xml"/>
    <import resource="/resources/themeSource.xml"/>

    <bean id="bean1" class="..."/>
    <bean id="bean2" class="..."/>
</beans>

使用bean

  • 属性
    • id为标识符。
    • name为别名,id优先。
    • class要实例化的类。
    • autowire自动装配
      • byName自动查找和set方法名字中set后面的字段相同的bean。
      • byType必须保证类型唯一。
      • constructor。
    • scope作用域
    • parent通过beanid继承另一个bean。
  • 注入方式
    • property。通过set注入值。
    • constructor-arg。通过构造方法注入值,和上一个同时注入一个属性的值时,先被调用,set后调用,最终值是set注入的值(官方推荐注入方式)。
    • 通过工厂方法注入。
    • 单例模式singleton对象的注入。
      • 实现ApplicationContextAware接口,不推荐,有耦合。
      • lookup-method,基于动态代理,见lookupTest。
      • 实现MethodReplacer接口。
        <bean id="dbUtils" class="com.etc.utils.DBUtil" factory-method="getInstance"/>
    
  • 集合(list、set、map、prop(Proprtties))
<bean id="moreComplexObject" class="example.ComplexObject">
    <!--使用parent属性合并集合-->
    <!--数组-->
    <property name="array">
        <array>
            <value>数组第一个数据</value>
            <value>数组第二个数据</value>
        </array>
    </property>
    <!-- results in a setAdminEmails(java.util.Properties) call -->
    <property name="adminEmails">
        <props>
            <prop key="administrator">administrator@example.org</prop>
            <prop key="support">support@example.org</prop>
            <prop key="development">development@example.org</prop>
        </props>
    </property>
    <!-- results in a setSomeList(java.util.List) call -->
    <property name="someList">
        <list>
            <value>a list element followed by a reference</value>
            <ref bean="myDataSource" />
        </list>
    </property>
    <!-- results in a setSomeMap(java.util.Map) call -->
    <property name="someMap">
        <map>
            <entry key="an entry" value="just some string"/>
            <entry key ="a ref" value-ref="myDataSource"/>
        </map>
    </property>
    <!-- results in a setSomeSet(java.util.Set) call -->
    <property name="someSet">
        <set>
            <value>just some string</value>
            <ref bean="myDataSource" />
        </set>
    </property>
</bean>
  • 其它
    • 内部类用$
    • property等中可以配置inner bean
    <bean id="outer" class="...">
        <!-- instead of using a reference to a target bean, simply define the target bean inline -->
        <property name="target">
        <bean class="com.example.Person"> <!-- this is the inner bean -->
            <property name="name" value="Fiona Apple"/>
            <property name="age" value="25"/>
        </bean>
        </property>
    </bean>
    
    • 空值("")和null()
    • p和c命名空间就是指,更简洁但更不灵活,用法
    <bean name="classic" class="com.example.ExampleBean">
        <property name="email" value="someone@somewhere.com"/>
    </bean>
    
    <bean name="p-namespace" class="com.example.ExampleBean"
        p:email="someone@somewhere.com"/>
    <bean id="beanOne" class="x.y.ThingOne" c:_0-ref="beanTwo" c:_1-ref="beanThree"
      c:_2="something@somewhere.com"/>
    
    • 一个bean引用另一个bean时,为确保其已被初始化,用depends-on属性
    <bean id="beanOne" class="ExampleBean" depends-on="manager"/>
    <bean id="manager" class="ManagerBean" />
    
    • 延迟初始化lazy-init,不在程序开始时初始化,而在第一次被请求时初始化。

注解

扫描包的注解以及启用注解

<context:component-scan base-package="com.ma.pojo"/>
<context:annotation-config/>

加速扫描添加下列依赖,生成META-INF/spring.components文件,spring会使用这个文件而不是扫描classpath。

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-indexer</artifactId>
        <version>5.2.4.RELEASE</version>
        <optional>true</optional>
    </dependency>
  • @Bean。A中getB()上加上@Bean,就不用在配置文件中建。例如使用第三方库。
  • @Required。弃用。
  • @Autowired。自动装配。默认时byName方式,找不到会使用其它方式。使用@Bean和@Primary确定自动装配的bean可以在属性、构造方法、set方法上。
  • @Resource。类似@Autowired。
  • @Qualifier。当有多个实现类时,自动装配无法确定哪个实现类,用它指定。
  • @Value。直接赋值从配置文件中或者properties文件中获取值。
  • @PostConstruct and @PreDestroy。对象创建和销毁时的动作。
  • @Component。将类放给spring托管,相当于写了一个。@Repository, @Service, and @Controller功能一样。
  • @Scope。作用域,和配置文件中的scope属性作用一样。

基于Java配置Spring

  • 编写配置类
@Configuration
@ComponentScan("com.ma.pojo")
//@Import(xxx.class)
//...other config
public class SpringConfig {

    //方法名相当于id,返回值相当于class。
    @Bean
    public Hello getHello(){
        return new Hello();
    }
}
  • 获取Context
    ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

环境的抽象

  • @Profiles。将类、方法分配到不同开发环境。默认为default开发环境。
    添加@Profiles。
    @Bean
    @Profile("dev")
    public Hello getHello(){
        return new Hello();
    }

为context设置环境(可以添加多个)和配置类(可以多个)。

    @Test
    public void javaConfigTest(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.getEnvironment().setActiveProfiles("dev");
        context.register(SpringConfig.class);
        context.refresh();
        Hello hello=context.getBean("getHello",Hello.class);
        System.out.println(hello);
    }
  • @Properties。加载properties配置文件。
@Configuration
@PropertySource("classpath:/com/myco/app.properties")
public class AppConfig {

    @Autowired
    Environment env;

    @Bean
    public TestBean testBean() {
        TestBean testBean = new TestBean();
        testBean.setName(env.getProperty("testbean.name"));
        return testBean;
    }
}

ApplicationContext

资源加载器(ResourceLoader)

  • 使用MessageSource进行国际化。
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    ...
</bean>
  • eventlistener

Resources

类似Java的资源加载,但更系统、更强大。

Validation, Data Binding, and Type Conversion

  • Validation。对javabean的数据校验。实现Validator接口自定义校验类。
  • Data Binding。数据绑定,将数据提交给app。spring提供DataBinder类来帮助我们实现。
  • Type Conversion。对属性进行类型转换。实现Converter、ConverterFactory接口自定义类型转换类。

Spring Expression Language (SpEL)

spring表达式。最经典的就是 "#{}" 获取资源。支持算术运算、比较运算、条件运算、逻辑运算、正则表达式(matches)、类型判断(instanceof)。可以从bean、xml、properties、集合、方法、类(T())、对象中获取资源。

AOP

面向切面编程,代码上想添加日志、监控等,放在核心代码里变扭。
AOP实现方式:

  • 编译class时织入,AspectJ。
  • 运行时织入,Spring。
    代理:
  • 静态代理,编写接口并实现两次,一个真实对象和一个代理对象,代理对象中调用真实对象的方法。
  • 动态代理,Spring采用的。借用Java中 Proxy 类与 InvocationHandler 接口
    实现InvocationHandler接口
public class ProxyInvocaionHandle implements InvocationHandler {
    Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        logBrfore(method.getName());
        Object result=method.invoke(target,args);
        logAfter(method.getName());
        return result;
    }

    public void logBrfore(String msg){
        System.out.println("use "+msg+" function");
    }

    public void logAfter(String msg){
        System.out.println("use "+msg+" function");
    }

}

使用

        //真实角色
        UserServiceImp useService=new UserServiceImp();
        //代理角色生成器
        ProxyInvocaionHandle pih=new ProxyInvocaionHandle();
        //设置要代理的对象
        pih.setTarget(useService);
        //动态生成代理类
        UserService proxy=(UserService)pih.getProxy();

        proxy.query();

Spring实现AOP

  • Spring原生API方式
    <bean id="userService" class="com.ma.service.UserServiceImp"/>
    <bean id="beforeLog" class="com.ma.log.BeforeLog"/>
    <bean id="afterLog" class="com.ma.log.AfterLog"/>

    <!--使用原生Spring API接口-->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.ma.service.UserService.*(..))"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
    </aop:config>
  • 自定义类
public class Annotation {

    public void before(){
        System.out.println("方法执行前");
    }
}

Spring中配置

    <!--自定义类-->
    <bean id="diy" class="com.ma.diy.Annotation"/>
    <aop:config>
        <aop:aspect ref="diy">
            <aop:pointcut id="point" expression="execution(* com.ma.service.UserService.*(..))"/>
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>
  • 使用注解实现
@Aspect
public class Annotation {

    @Before("execution(* com.ma.service.UserServiceImp.*(..))")
    public void before(){
        System.out.println("方法执行前");
    }

    @After("execution(* com.ma.service.UserServiceImp.*(..))")
    public void after(){
        System.out.println("方法执行后");
    }
}

SpringAOP通知(advice)类型

  • Before
  • After
  • After returning
  • After throwing advice: Advice to be executed if a method exits by throwing an exception.
  • After (finally) advice: Advice to be executed regardless of the means by which a join point exits (normal or exceptional return).
  • Around advice: Advice that surrounds a join point such as a method invocation. This is the most powerful kind of advice. Around advice can perform custom behavior before and after the method invocation. It is also responsible for choosing whether to proceed to the join point or to shortcut the advised method execution by returning its own return value or throwing an exception.

SpringAOP为类增加新的功能

区别于日志、监控等功能,增加的功能是类的核心功能。

<aop:declare-parents
        types-matching="com.xzy.myapp.service.*+"
        implement-interface="com.xyz.myapp.service.tracking.UsageTracked"
        default-impl="com.xyz.myapp.service.tracking.DefaultUsageTracked"/>
原文地址:https://www.cnblogs.com/Tig3r/p/13128928.html