Spring Framework -- 业务层

官网:https://spring.io/projects/spring-framework
历史:澳大利亚人Rod Johnson,2004年发布了Spring Framework,同年成立 interface21公司, 2007 年更名为 SpringSource,2009年被 VMWare 收购,2013 年Spring 项目被转到VMware投资的 Pivotal 软件公司。

概念
Java Bean:需要交给容器管理的对象
Spring Bean容器:根据配置文件生成并管理Bean实例 的框架对象,又叫Spring IoC容器
IoC:Inversion of Control,控制反转;主程序从Bean容器中获取所需Bean,而不是自己生成和管理;即对Bean的控制权从主程序反转到了Bean容器。
DI:Dependency Injection,依赖注入;Bean A 依赖 Bean B(即A持有一个B),主程序从Bean容器中获取A时,容器会自动把B注入到A中。
AOP:Aspect Oriented Programming,面向切面的编程。通过动态代理,在主程序前后织入切面逻辑(拦截器)
EJB:企业级Java Bean,是Sun出品的Java ee框架,运行在EJB容器上,例如Weblogic、Websphere
Spring MVC:Spring MVC 是 Spring Framework的一个特性
SSH:Struts + Spring Framework + Hibernate
SSM:Spring MVC + Spring Framework + MyBatis

动态代理 结合 拦截器

// 拦截器接口
public interface Interceptor {
    public boolean before();
    public void around();
    public void after();
}
// 动态代理类中
private Interceptor interceptor; // 持有一个拦截器
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object result = null;
    if(interceptor.before()) {       // befroe()返回true,则执行 invoke,否则执行 around
        result = method.invoke(object, args);
    }
    else{
        interceptor.around();
    }
    interceptor.after();
    return result;
}

动态代理 结合 责任链模式

// 服务对象(被代理对象)
BuyHouse target = new BuyHouseImpl();
// 动态处理器实例,接收一个拦截器
DynamicProxyHandler dph = new DynamicProxyHandler(buyHouse, interceptor1);
// 代理实例
BuyHouse proxy1 = (BuyHouse) Proxy.newProxyInstance(target .getClass().getClassLoader(), target.getClass().getInterfaces(), dph); 

// 前一个代理实例 作为 后一个代理实例的服务对象
dph = new DynamicProxyHandler(proxy1, interceptor1);
BuyHouse proxy2 = (BuyHouse) Proxy.newProxyInstance(proxy1.getClass().getClassLoader(), proxy1.getClass().getInterfaces(), dph); 

proxy2.buyHosue();  // proxy2代理了proxy1,proxy1代理了target

术语
Context:Bean容器
profile:场景

总结
Bean的装载:扫描注解@Service、@Bean、@Component
Bean的获得:ApplicationContext.getBean()、@Autowired自动注入,xml中 ref 引用

IDEA 配置 Spring
1、在Maven中央仓库或Maven搜索服务上查找Spring,配置Maven依赖


    org.springframework
    spring-core   
    5.0.8.RELEASE


    org.springframework
    spring-beans   
    5.0.8.RELEASE


    org.springframework
    spring-context   
    5.0.8.RELEASE

2、右键 -> Add Frameworks Support -> 勾选Spring,勾选自动生成spring-config.xml

通过XML配置 装配Bean

1、Bean类
2、Bean配置文件,spring-config.xml


  
  

    
        
        
    
    
    
        
        
        
    

    
            
            
                value-list-1
                value -list-2
                    
            
        
            
            
                
                
                    
           
       
           
           
               value-prop-1
              value-prop-2
              value-prop-3
          
       
           
           
               value-set-1
               value-set-2
                   
          
      
          
          
              value-array-1
              value-array-2
              value-array-3
          
       
   

3、使用

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

  // 读取Bean配置文件,初始化Bean,依赖注入,放入Bean容器ApplicationContext
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
Country country = (Country) ctx.getBean ("country");    // 通过Bean Id 得到 Bean实例
System.out.println(country.getCountryName());

Bean生命周期
初始化开始 ->
调用Bean类的setBeanName,来自BeanNameAware接口 ->
调用Bean类的setBeanFactory(BeanFactory),来自BeanFactoryAware接口 ->
调用Bean类的setApplicationContext(ApplicationContext),来自ApplicationContextAware接口 ->
调用Bean类的postProcessBeforelnitialization(bean,beanName),来自BeanPostProcessor接口 ->
初始化属性 ->
调用Bean类的afterPropertiesSet(),来自InitializingBean接口 ->
调用Bean类的自定义初始化方法 ->
调用Bean类的postProcessAfterlnitialization(bean,beanName),来自BeanPostProcessor接口 ->
生存期 ->
调用Bean类的自定义销毁方法 ->
调用Bean类的destroy,来自DisposableBean接口

通过注解类 装配Bean

1、Bean类

import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.annotation.Autowired ;

@Component(value="city1")    // 相当于xml里的 bean id
public class City {
    @Value("1");                      // 相当于xml里的value
    private Long id;
    @Value("city_1")
    private String cityName ;
    @Value("86")
    private String countryCode;
    @Autowired       // 自动装配依赖,即容器自动查找同类Bean,并注入
    private Country country;
}

自动装配的歧义性:假设Country有两个子类Country1 和 Country2,且都被装配。那么容器无法确定给City注入哪个Country
消除歧义:
方法1、给Country1 增加注解 @Primary,则优先注入Country1
方法2、@Autowired
@Qualifier("country1") // 通过Bean Id 指明 依赖
private Country country = null;

2、Bean配置类,BeanConfig.java

import org.springframework.context.annotation.ComponentScan;

@Import({BeanConfig1.class, BeanConfig2.class})    // 导入其他BeanConfig
@ComponentScan(basePackages={"com.maven.hogen",”com.maven.hogen.bean"},    // 要扫描包
    basePackageClasses={City.class, Country.class})           // 要扫描的类
public class BeanConfig {
}

3、使用

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

// 扫描BeanConfig里配置的目标Bean,并装载到Bean容器
ApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);
City city = context.getBean(City.class );
System.out.println(city .getId()) ;

通过注解方法 装配Bean

前提:方法所在Java类能被扫描到

@Bean(name="city1", initMethod="init", destroyMethod="destroy")  // name 为 Bean Id
// 扫描到这时,会调用该方法,将其返回值作为Bean,进行装载
public City initCity () {
    return city;
}

装配方式选择:自定义的类用注解装配,第三方的类用XML装配

混合装配,同时通过XML和注释装配

@ComponentScan(basePackages={"com.maven.hogen"})
@ImportResource({"classpath:spring-dataSource.xml"})
public class ApplicationConfig {
}

场景设置
声明场景
Java中定义Bean的地方:@Profile("dev")
XML中加一层:
激活场景
Spring MVC配置文件中:

spring.profiles.active
test

Bean作用域
1、单例(Singleton),始终只有一个
2、会话(Session),每个会话一个
3、请求(request),每次请求一个
4、原型(prototype),每次从容器中获取,都得到新的一个
设置作用域:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

Spring EL(表达式语言)

import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

ExpressionParser parser = new SpelExpressionParser();
// 解析字符串,执行里面的语句
Expression exp = parser.parseExpression(" 'hello world'.charAt(0) ");
// 得到语句的值
char ch = (Character) exp.getValue();
System.out.println(ch);

// 调用getter的简写,.bytes 相当于 .getBytes()
exp = parser.parseExpression (" 'hello world'.bytes ");


exp = parser.parseExpression("cityName");
// 相当于取 city.cityName
String cityName = (String) exp.getValue(city) ;

// 把对象包装成 执行语句的上下文
EvaluationContext ctx =new StandardEvaluationContext (city);
parser.parseExpression("cityName").setValue(ctx, "Beijing");  // 设置属性
cityName = parser.parseExpression("cityName").getValue(ctx , String.class);  // 取值属性

// 将上下文设置为列表
ctx.setVariable("list", list);
// 通过表达式去读/写环境变量的值
parser.parseExpression("#list[1]").setValue(ctx, "value1");  // 设置列表元素
System.out.println(parser.parseExpression("#list[1]").getValue(ctx));  // 取值列表元素

在一个Bean中引用(注入)另一个Bean的值

@Component("beanName")
public class Country{
    @Value("#{city}")    // 引用Bean Id为city的Bean,来给city1初始化
    private City city1;

   @Value("#{city.id}")   // 引用属性
    private Long id;

   @Value("#{city.getCityName()}")  // 引用方法
    private String cityName;

   @Value("#{T(Math).PI}")    // 引用静态成员
    private double pi;
 
    @Value("#{city.cityName + city.note}")  // 运算后注入
    private String str;
}

Spring AOP
术语
Aspect:切面,即一组拦截器组成的类
Advice:拦截器
Weaving:织入
Pointcut:切点,即被拦截的方法
Join point:连接点,即切点中拦截器被织入的位置
AOP:将切面的拦截器织入到切点里的连接点
Spring AOP除了能处理用户提供的切面,同时提供一些常用切面,例如数据库事务

Spring AOP 组成
1、Bean
2、切面类

@Aspect                               // 注解为切面类
@Order(1)         // 一个切点可能被多个切面拦截,不注明顺序的话,是无序的
public class CityAspect{ 
     // * 表示任意返回值,(..) 表示任意参数
    @Before("execution(* com.maven.hogen.city.printCity( .. ))”)   // 位置+切点 = 连接点
    public void before () { // do something }             // 拦截器

    // 把切点的入参 传递给 拦截器
    @After("execution(* com.maven.hogen.city.printCity( .. )) && args(cityId,cityName)")
    public void after(int cityId, String cityName) { // do something } 

    @AfterReturning("execution(* com.maven.hogen.city.printCity( .. ))”)
    public void afterReturning () { // do something }

    @AfterThrowing("execution(* com.maven.hogen.city.printCity( .. ))”)
    public void afterThrowing() { //do someting }

    @Around("execution(* com.maven.hogen.city.printCity( .. ))”)   // 环绕拦截
    public void around(ProceedingJoinPoint jp) { 
        System.out.println (”before .. ..”) ; 
        try {jp.proceed();} 
        catch (Throwable e) { e.printStackTrace();}
        System.out.println (”after ....”);
    }

3、AOP配置类 AopConfig.java

@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.maven.hogen") 
public class AopConfig { 
    @Bean 
    public RoleAspect getRoleAspect() { return new CityAspect();}
}

4、使用

ApplicationContext ctx =new AnnotationConfigApplicationContext(AopConfig.class) ; 

引入(Introduction)

@Aspect
public class CityAspect{
    // 把City代理成一个CityVerifier的实现类,即cityVerifier是City的代理,并拥有CityVerifierImpl里实现的方法
    @DeclareParents(value="com.maven.hogen.City+”,  // + 表示增强
        defaultimpl=CityVerifierImpl.class)  // CityVerifierImpl 是 CityVerifier 的实现类
    public CityVerifier cityVerifier;  // CityVerifier 是个接口
}

你可能感兴趣的:(Spring Framework -- 业务层)