美文网首页
【JAVA】Spring

【JAVA】Spring

作者: Y了个J | 来源:发表于2017-10-28 22:13 被阅读20次

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

方便解耦,简化开发  (高内聚低耦合)
•   Spring就是一个大工厂(容器),可以将所有对象创建和依赖关系维护,交给Spring管理
•   spring工厂是用于生成bean
AOP编程的支持
•   Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
声明式事务的支持
方便程序的测试
•   Spring对Junit4支持,可以通过注解方便的测试Spring程序
方便集成各种优秀框架
•   Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持
降低JavaEE API的使用难度
•   Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低

1.IOC控制反转

将我们创建对象的控制权反转交给spring去创建

  • 之前创建对象是这么写的
UserService userService = new UserServiceImpl();
userService.addUser();
  • 现在都由spring来创建,后面开发也都通过扫描配置文件里注入的bean,对象直接从spring容器获取不需要自己创建
在xml里配置bean
<bean id="userServiceId" class="com.itheima.a_ioc.UserServiceImpl"></bean>

1 获得容器
String xmlPath = "com/itheima/a_ioc/beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
2获得内容 -- 不需要自己new,都是从spring容器通过id获得
UserService userService = (UserService) applicationContext.getBean("userServiceId");
userService.addUser();

2.DI依赖注入

service里是这么写的,通过setBookDao方法进行注入bookDao

private BookDao bookDao;

public void setBookDao(BookDao bookDao) {
    this.bookDao = bookDao;
}

@Override
public void addBook(){
    this.bookDao.save();
}

上面可以像下面这样用spring配置文件实现,使用<property> 用于进行属性注入

<!-- 创建service -->
<bean id="bookServiceId" class="com.itheima.b_di.BookServiceImpl" >
   <property name="bookDao" ref="bookDaoId"></property>
</bean>
   
<!-- 创建dao实例 -->
<bean id="bookDaoId" class="com.itheima.b_di.BookDaoImpl"></bean>

3.核心Api

BeanFactory :这是一个工厂,用于生成任意bean,采取延迟加载,第一次getBean时才会初始化Bean,懒加载
ApplicationContext:是BeanFactory的子接口,功能更强大。(国际化处理、事件传递、Bean自动装配、各种不同应用层的Context实现)。当配置文件被加载,就进行对象实例化,饿汉式,直接会实例bean

ClassPathXmlApplicationContext 用于加载classpath(类路径、src)下的xml
加载xml运行时位置 --> /WEB-INF/classes/...xml

FileSystemXmlApplicationContext 用于加载指定盘符下的xml
加载xml运行时位置 --> /WEB-INF/...xml
通过java web ServletContext.getRealPath() 获得具体盘符

4.装配bean

  • 默认构造
    <bean id="" class="">
  • 静态工厂
    常用与spring整合其他框架(工具)
    静态工厂:用于生成实例对象,所有的方法必须是static
    <bean id="" class="工厂全限定类名" factory-method="静态方法">

例如:bean.xml配置文件
<bean id="userServiceId" class="com.itheima.c_inject.b_static_factory.MyBeanFactory" factory-method="createService"></bean>

public class MyBeanFactory {
/**
* 创建实例
* @return
*/
public UserService createService(){
    return new UserServiceImpl();
    }
}

String xmlPath = "com/itheima/c_inject/b_static_factory/beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
UserService userService = applicationContext.getBean("userServiceId" ,UserService.class);
userService.addUser();
通过userServiceId获得factory并调用createService方法
  • 实例工厂
    必须先有工厂实例对象,通过实例对象创建对象。提供所有的方法都是“非静态”的。

5.作用域

image.png

singleton 单例,默认值。
prototype 多例,每执行一次getBean将获得一个实例。例如:struts整合spring,配置action多例。

6.生命周期

  • 初始化和销毁
    <bean id="" class="" init-method="初始化方法名称" destroy-method="销毁的方法名称">
    目标类
public class UserServiceImpl implements UserService {
    @Override
    public void addUser() {
        System.out.println("e_lifecycle add user");
    }
    
    public void myInit(){
        System.out.println("初始化");
    }
    public void myDestroy(){
        System.out.println("销毁");
    }
}

spring配置

<!--  
    init-method 用于配置初始化方法,准备数据等
    destroy-method 用于配置销毁方法,清理资源等
-->
<bean id="userServiceId" class="com.itheima.e_lifecycle.UserServiceImpl" 
init-method="myInit" destroy-method="myDestroy" ></bean>
    
<!-- 将后处理的实现类注册给spring -->
<bean class="com.itheima.e_lifecycle.MyBeanPostProcessor"></bean>

测试

@Test
public void demo02() throws Exception{
    //spring 工厂
    String xmlPath = "com/itheima/e_lifecycle/beans.xml";
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
    UserService userService = (UserService) applicationContext.getBean("userServiceId");
    userService.addUser();
        
    //要求:1.容器必须close,销毁方法执行; 2.必须是单例的
       //applicationContext.getClass().getMethod("close").invoke(applicationContext);
    // * 此方法接口中没有定义,实现类提供
    applicationContext.close(); 
}

BeanPostProcessor 后处理Bean

spring 提供一种机制,只要实现此接口BeanPostProcessor,并将实现类提供给spring容器,spring容器将自动执行,在初始化方法前执行before(),在初始化方法后执行after() 。 配置<bean class="">
spring提供工厂勾子,用于修改实例对象,可以生成代理对象,是AOP底层。


public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("前方法 : " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
        System.out.println("后方法 : " + beanName);
        // bean 目标对象
        // 生成 jdk 代理
        return Proxy.newProxyInstance(
                    MyBeanPostProcessor.class.getClassLoader(), 
                    bean.getClass().getInterfaces(), 
                    new InvocationHandler(){
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            System.out.println("------开启事务");
                            
                            //执行目标方法
                            Object obj = method.invoke(bean, args);
                            
                            System.out.println("------提交事务");
                            return obj;
                        }});
    }
}

将后处理的实现类注册给spring
<bean class="com.itheima.e_lifecycle.MyBeanPostProcessor"></bean>

问题1:后处理bean作用某一个目标类,还是所有目标类?
所有
问题2:如何只作用一个?
通过“参数2”beanName进行控制

Bean的生命周期,生命周期详情

  1. instantiate bean对象实例化
  2. populate properties 封装属性
  3. 如果Bean实现BeanNameAware 执行 setBeanName
  4. 如果Bean实现BeanFactoryAware 或者 ApplicationContextAware 设置工厂 setBeanFactory 或者上下文对象 setApplicationContext
  5. 如果存在类实现 BeanPostProcessor(后处理Bean) ,执行postProcessBeforeInitialization
  6. 如果Bean实现InitializingBean 执行 afterPropertiesSet
  7. 调用<bean init-method="init"> 指定初始化方法 init
  8. 如果存在类实现 BeanPostProcessor(处理Bean) ,执行postProcessAfterInitialization
  9. 执行业务处理
  10. 如果Bean实现 DisposableBean 执行 destroy
  11. 调用<bean destroy-method="customerDestroy"> 指定销毁方法 customerDestroy

相关文章

网友评论

      本文标题:【JAVA】Spring

      本文链接:https://www.haomeiwen.com/subject/blhepxtx.html