Fork me on GitHub

JavaEE Day06 Spring

Day06 Spring


spring简介

什么是spring

spring产生于2003年,轻量级javase/ee 一站式开源框架
ejb:javabean

spring在三层架构的地位

  1. 表示层:spring MVC/struts2
  2. 业务逻辑层:spring framework
  3. 数据持久层:mybatis、hibernate、JdbcTemplate

spring的产生背景

  1. 单一设计原则
  2. 面向扩展开放,面向修改关闭
  3. 依赖倒置,不要实体类之间的关联过高,通过接口来实现;

spring的优点

  1. 方便解耦,简化开发(高内聚,低耦合)
  2. spring是工厂,负责创建对象以及对象关系的维护;
  3. 支持aop编程(面向切面编程)
  4. spring支持对优秀框架的集成
  5. spring支持对javaee api的简化
  6. spring支持对junit的整合

spring的体系结构

http://www.spring.io

spring的核心

-w503

  1. ioc:控制反转
  2. aop:面向切面

入门案例

ioc:控制反转。将对象创建和依赖管理的权限反转给spring、容器。

DI:依赖注入

创建java项目。导入jar

核心容器jar+commons_logging(日志增强)

步骤:

├─applicationContext.xml
├─dao
│  ├─UserDao.java
│  └─impl
│        └─UserDaoImpl.java
├─service
│  ├─UserService.java
│  └─impl
│        └─UserServiceImpl.java
└─test
      └─Test.java
  1. 创建lib目录,导入spring的jar包,spring-beans,spring-context,spring-core,srping_expression(不是javadoc和source),日志文件:导入mybatis中的commons-logging.jar即可
  2. 创建dao包,在包下创建接口UserDao
  3. 在dao包下创建impl包,在impl包下创建userDaoImpl实现类,不需要连接数据库,直接打印一段文字即可
  4. 在src目录下创建applicationContext.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定义在这里 -->  
        <!-- bean:代表配置管理一个对象
        		id:唯一标识
        		class:类的完全限定名称
        
         -->
        <bean id="userdao" class="dao.impl.UserDaoImpl"></bean>
    </beans>
    
  5. 新建测试类
    import java.lang.reflect.InvocationTargetException;
    
    public class Test {
       public static void main(String[] args) {
           // 创建管理对象权限 ---> 自身
           // spring容器先创建和管理dao(配置文件)
           // 从spring容器中获取dao对象
           // UserDao dao = new UserDaoImpl();
           ApplicationContext ac =
                   new ClassPathXmlApplicationContext("applicationContext.xml");
           UserDao dao = ac.getBean("userdao", UserDao.class);
           dao.addUser();
           dao.deleteUser();
       }
    }
    
    此处建议使用接口,方便

对象创建方式

<?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定义在这里 -->  
    <!-- bean:代表配置管理一个对象
    		id:唯一标识
    		class:类的完全限定名称
    
     -->
    <bean id="userdao" class="dao.impl.UserDaoImpl"></bean>

    <!--调用无参构造+setter方法创建-->
    <!--<bean id="userservice" class="service.impl.UserServiceImpl">
        &lt;!&ndash;给属性赋值 name:属性的名称(setDao方法) value:简单类型值 ref:引用&ndash;&gt;
        <property name="dao" ref="userdao"></property>
    </bean>-->

    <!--使用有参构造-->
    <bean id="userservice" class="service.impl.UserServiceImpl">
        <!--构造器参数: name:参数名称 value:简单类型值 ref:引用 index:参数的索引 type:参数的类型-->
        <!--<constructor-arg name="dao" ref="userdao"></constructor-arg>-->
        <constructor-arg index="0" ref="userdao"></constructor-arg>
    </bean>
</beans>

调用方法

package test;

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

import pojo.User;
import service.UserService;

import java.lang.reflect.InvocationTargetException;

public class Test {
	public static void main(String[] args) {
		// 创建管理对象权限 ---> 自身
		// spring容器先创建和管理dao(配置文件)
		// 从spring容器中获取dao对象
//		UserDao dao = new UserDaoImpl();
		/*ApplicationContext ac =
				new ClassPathXmlApplicationContext("applicationContext.xml");
		UserDao dao = ac.getBean("userdao", UserDao.class);
		dao.addUser();
		dao.deleteUser();*/

		/*UserService service = new UserServiceImpl();
		service.addUser();
		service.deleteUser();*/

		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserService service = ac.getBean("userservice",UserService.class);
		service.addUser();
		service.deleteUser();
        
    }
}

bean声明周期

-w324

目录结构

├─applicationContext.xml
├─pojo
│  └─User.java
└─test
      └─Test.java

applicationContext.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="user" class="pojo.User" init-method="init" destroy-method="destory">
        <property name="uid" value="1"></property>
    </bean>

</beans>

User.java


package pojo;

public class User {
    private int uid;
    private String username;

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void init(){
        System.out.println("初始化");
    }

    public void destory(){
        System.out.println("销毁");
    }
}

test.java

package test;

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

import pojo.User;
import service.UserService;

import java.lang.reflect.InvocationTargetException;

public class Test {
	public static void main(String[] args) {
		// 创建管理对象权限 ---> 自身
		// spring容器先创建和管理dao(配置文件)
		// 从spring容器中获取dao对象

		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = ac.getBean("user", User.class);
        System.out.println(user);
        try {
            ac.getClass().getMethod("close").invoke(ac);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

注解实现bean的装配

前提:需要spring-aop.jar

  1. @Component:创建对象 等价于
  2. @Compoenet("id"):创建对象 等价于
  3. @Controller: 表示层创建对象
  4. @Service:业务逻辑层创建对象
  5. @Repository:数据持久层创建对象
  6. @Autowired: 按照类型自动注入(找不到:不注入,找到一个:注入成功,找到多个:报异常),在私有属性上配置
  7. 按照名称注入
    1. @Autowired
      @qualifier("name") 配置私有属性的名字
    2. @Resource(name="name")

步骤

目录结构

├─applicationContext.xml
├─dao
│  ├─UserDao.java
│  └─impl
│       └─UserDaoImpl.java
├─service
│  ├─UserService.java
│  └─impl
│        └─UserServiceImpl.java
└─test
     ├─Test.java
     └─Test2.java

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--schema:通过namespace规范标签-->
<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">

    <!-- bean definitions here -->
    <!--  通过包名进行扫描,-->
    <context:component-scan base-package="dao,service"></context:component-scan>
</beans>

和不使用注解时一样,只是在创建applicationContext.xml时的配置不同

  1. 新增context的命名空间
  2. 追加schemaLocation:context和spring-context.xsd
  3. 使用context:componenet-scan,扫描所有的主包

UserDao.java

package dao;

public interface UserDao {
    void addUser();
    void deleteUser();
}

UserDaoImpl.java

package dao.impl;

import dao.UserDao;
import org.springframework.stereotype.Repository;


@Repository("userdao")
public class UserDaoImpl implements UserDao {

    @Override
    public void addUser() {
        System.out.println("添加用户");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }
}

UserService.java

package service;

public interface UserService {
    void addUser();
    void deleteUser();
}

UserServiceImpl.java

package service.impl;

import dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import service.UserService;

@Service("userservice")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao dao;

    @Override
    public void addUser() {
        dao.addUser();
    }

    @Override
    public void deleteUser() {
        dao.deleteUser();
    }
}

Test.java

package test;

import dao.UserDao;

import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import service.UserService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class Test {

    @Autowired
    UserService service;

    @org.junit.Test
    public void text(){
    	service.addUser();
    	service.deleteUser();
    }
    
    
    
    /*public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//        UserDao userdao = ac.getBean("userdao", UserDao.class);
//        userdao.addUser();
//        userdao.deleteUser();
        UserService userservice = ac.getBean("userservice", UserService.class);
        userservice.addUser();
        userservice.deleteUser();
    }*/
}

spring整合junit

Junit:用于单元测试。spring整合junit 在spring-test.jar包中

  1. junit使用:导入junit(junit 4)
  2. ecplise 直接在项目的目录名右击,build-path,add-lib,选择junit
  3. idea 中,注解@org.junit.Text,然后使用alt+endter,或者使用⌘ Cmd+ Shift+T

代理

对象访问前后实现预处理,过滤等处理

代理模式

静态代理

  1. 编译期间为每个委托类创建代理类
  2. 代理类和委托类实现同一个接口

委托类

public class UserServiceImpl implements UserService {

    @Override
    public void addUser() {
        System.out.println("添加用户");
    }

    @Override
    public void deleteUser() {
        System.out.println("删除用户");
    }
}

代理类

package service.proxy;

import service.UserService;

/**
 * 代理类 静态代理
 */
public class UserServiceProxy implements UserService {

//    UserService service = new UserServiceImpl_bak();
    UserService service;

    public UserServiceProxy(UserService service) {
        this.service = service;
    }

    @Override
    public void addUser() {
        System.out.println("开启事务");
        service.addUser();
        System.out.println("提交事务");
    }

    @Override
    public void deleteUser() {
        System.out.println("开启事务");
        service.deleteUser();
        System.out.println("提交事务");
    }
}

Text.java

package test;

import service.UserService;
import service.impl.UserServiceImpl_bak;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Test {



/*  // 静态代理
    @org.junit.Test
    public void test(){
//        UserService service = new UserServiceImpl_bak();
        UserService service = new UserServiceProxy(new UserServiceImpl_bak());
        service.addUser();
        service.deleteUser();
    }
}

动态代理

  1. 运行期间为每个委托类的对象创建代理对象;
  2. 采用反射机制
    1. 接口+实现类(JDK的动态代理)
    2. 实现类(cglib的动态代理)继承实现

测试类

只需要实现类或者实现类+接口即可

package test;

import service.UserService;
import service.impl.UserServiceImpl_bak;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Test {



/*  // 静态代理
    @org.junit.Test
    public void test(){
//        UserService service = new UserServiceImpl_bak();
        UserService service = new UserServiceProxy(new UserServiceImpl_bak());
        service.addUser();
        service.deleteUser();
    }*/

    // 无侵入式增强
    @org.junit.Test
    public void test() {
        // 1. 创建委托类对象
        UserService service = new UserServiceImpl_bak();

        // 2. 为委托类对象创建动态代理对象
        UserService proxy = (UserService) Proxy.newProxyInstance(
                service.getClass().getClassLoader(),
                service.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("开启事务");
                        // 手动调用方法              委托类对象
                        Object obj = method.invoke(service, args);
                        System.out.println("提交事务");
                        return obj;
                    }
                }
        );

        // 3. 为调用代理对象
        proxy.addUser();
        System.out.println("*************");
        proxy.deleteUser();
    }

}

aoP

面向切面编程,采用横向抽取方式,在运行阶段将增强代码植入目标对象的思想;底层采用动态代理

aop应用场景

事务管理,日志系统,性能监测,缓存等等。。。。。

aop框架

  1. Sprin aop(spring-aop,jar)
  2. Aspectj(aspectj.jar)
  3. Jboos

Aop的专业术语

  1. target: 目标对象,添加增强代码的对象,(委托类)
  2. advice:通知,增强代码 (遵循特定规范的增强代码)
  3. joinpoint:连接点,目标对象方法
  4. pointcut:切入点,真正添加增强目录对象的方法
  5. weaver:织入 增强代码添加到切入点的过程。
  6. aspect:切面,增强代码和切入点连接形成逻辑面。

aop编程

  1. 导入jar

    1. 4+1(spring的核心包,日志包)
    2. Spring-aop.jar:spring aop框架
    3. Spring-aspects.jar :aspectj规范
    4. Aopaliance-1.0.jar:aop联盟(规范通知)
    5. Aspectjweaver.jar:实现织入
    6. 导入spring-text。Jar
  2. 准备一个接口+实现类(委托类)

    1. 接口:

      package service;
      
      public interface UserService {
          void addUser();
          void deleteUser();
      }
      
    2. 实现类

      package service.impl;
      
      import org.springframework.stereotype.Service;
      import service.UserService;
      import txAdvice.TxAdvice;
      
      
      public class UserServiceImpl implements UserService {
      
          @Override
          public void addUser() {
              tx.before();
              System.out.println("添加用户");
              tx.after();
          }
      
          @Override
          public void deleteUser() {
              tx.before();
              System.out.println("删除用户");
              tx.after();
          }
      }
      
      
  3. 准备一个增强代码(代理类中多余的代码,新增的功能)

    package aspect;
    
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;
    
    
    public class MyAspect {
    
        public void before(){
            System.out.println("开启事务");
        }
    
       
        public void after(){
            System.out.println("提交事务");
        }
    }
    
    
  4. 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"
           xmlns:aop="http://www.springframework.org/schema/aop"
           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">
    
        <!-- 1. 创建目标类的对象-->
            <bean id="userservice" class="service.impl.UserServiceImpl_bak_bak"></bean>
        <!-- 2. 创建增强代码类对象-->
            <bean id="myaspect" class="aspect.MyAspect"></bean>
        <!-- 3. 织入增强代码 -->
            <aop:config>
                <!-- 配置切入点 expression:excution(返回值 包名.类型.方法名(参数列表))
                    *: 通配符 返回值
                    ..* : 包下的以及所有子包下的所有方法
                    .. : 参数列表任意
                 -->
                <aop:pointcut id="myPointcut" expression="execution(* service..*(..))"></aop:pointcut>
                <!-- 配置切面  ref:增强代码类-->
                <aop:aspect  ref="myaspect">
                    <!-- 前置增强 mothod:增强代码来的方法名     切入点-->
                    <aop:before method="before" pointcut-ref="myPointcut"/>
                    <!-- 后置增强 -->
                    <aop:after-returning method="after" pointcut-ref="myPointcut"/>
                </aop:aspect>
            </aop:config>
    </beans>
    
  5. 使用junit4来测试

     package test;
     
     import org.junit.runner.RunWith;
     import org.springframework.beans.factory.annotation.Autowired;
     import org.springframework.test.context.ContextConfiguration;
     import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
     import service.UserService;
     
     @RunWith(SpringJUnit4ClassRunner.class)
     @ContextConfiguration(locations = "classpath:applicationContext.xml")
     public class Test1 {
     
         @Autowired
         UserService service;
     
         @org.junit.Test
         public void test(){
             service.addUser();
             service.deleteUser();
         }
     }
    
    

apo 注解编程

接口

package service;

public interface UserService {
    void addUser();
    void deleteUser();
}

实现类

package service.impl;

import org.springframework.stereotype.Service;
import service.UserService;
import txAdvice.TxAdvice;

/**
 * 委托类
 */

@Service("userservice")
public class UserServiceImpl implements UserService {


    @Override
    public void addUser() {

        System.out.println("添加用户");

    }

    @Override
    public void deleteUser() {

        System.out.println("删除用户");

    }
}

增强代码类

package aspect;

import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component("myaspect")
@Aspect
public class MyAspect {
    // 异常增强
    // @AfterThrowing
    // 最终增强
    // @After
    // 环绕增强(必须手动调用目标方法)
    // @Around

   @Pointcut("execution(* service..*(..))")
    public void pointCut(){}

    @Before("pointCut()")
    public void before(){
        System.out.println("开启事务");
    }

    @AfterReturning("pointCut()")
    public void after(){
        System.out.println("提交事务");
    }
}

applicationContext.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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
http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd">


    <context:component-scan base-package="aspect,service"></context:component-scan>
    <!-- 自动实现代理-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>


</beans>

测试类

package test;

import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import service.UserService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class Test1 {

    @Autowired
    UserService service;

    @org.junit.Test
    public void test(){
        service.addUser();
        service.deleteUser();
    }
}

最好使用java1.8,否则很可能报错

posted @ 2018-10-28 10:25  耳_东  阅读(129)  评论(0)    收藏  举报