Skip to content

Latest commit

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

spring

Spring concept

Open-source framework, starts from 2003, light-weight, full-stack.

Features core content

  • AOP: 面向切面,扩展功能不是修改源代码实现。

  • IOC (控制反转), 比如有一个类,在类里面有方法(不是静态方法),调用类里面的方法,使用对象调用方法,创建类对象过程,需要new出来对象 把对象的创间不是通过new方法实现,而是交给spring配置创建类对象。

spring是一站式框架

  • spring, provides all layers solutions.
  • Web layer: springMVC

  • service layer: IoC of Spring

  • dao layer: jdbcTemplate of Spring

spring version 4.x

How to use IoC in Spring

把对象的创建交给spring进行管理

ioc操作包括两部分

*ioc的配置文件

*ioc的注解方式

IoC 原理

使用技术:1. xml配置文件; 2. dom4j解析xml; 3. 工厂的设计模式; 4. 反射技术

Code 原理

publicclassUser{
publicvoidadd() {
.....
}
}
// Call method - old way /* 在servlet中调用User类里面的内容,如果类名和方法发生改变,需要改变的东西太多。 耦合度太高了。*/Useruser = newUser();
user.add();

使用工厂模式解决耦合操作

publicclassUserService {
publicvoidadd() {
}
}
publicclassUserServlet{
UserServiceuserService = UserFactory.getService();
userService.add();
}
// Solution: create factory class. publicclassUserFactory{
// provide one method returns UserService object. publicstaticUserServicegetService() {
returnnewUserService();
}
}

思想: 高内聚,低耦合

IoC concept (*)

publicclassUserService{
}
publicclassUserServlet {
// get object UserServiceUserFactory.getService();
}
/** Step 1. Create xml file, configure to class you want to create.  <bean id="userService" class="com.liyiandxuegang.package.UserService" /> Step 2. Create one Factory class, use dom4j to parse configuration file + reflection tech. public class UserFactory{ // return UserService  public static UserService getService() { // 1. Use dom4j parse xml file.  // According to id value, get the class property value responding to the id. String classValue = "from xml class property value"; // 2. Use reflection create object Class clazz = Class.forName(classValue); // 3. Use reflection create object UserService userService = clazz.newInstance(); return userService;  } }	*/

IoC (Inversion of Control) basic Example

  • Step 1. Import jar files

    (1) Release.jar, javadoc.jar, sources.jar

    (2) Basic jars: Beans, Core, Context, SpEL (Core container)

    (3) Import logging.jar

  • Step 2. Create class and method inside of class.

  • Step 3. create spring xml file, configure the class

    • Spring core configuration name and location is not fixed. But better under /src.

    • 引入约束 schema

    • Configure the class

  • Step 4. Create test.

@TestpublicvoidtestUser() {
//1. load configuration fileApplicationContextapplicationContext = newClassPathXmlApplicationContext("bean1.xml");
//2. Get objectUseruser = (User) applicationContext.getBean("user");
//3. Testuser.add();
}

Manage bean in spring (xml)

  • Bean 实例化方式
  1. 在spring里面通过配置文件创建对象

  2. bean实例化三种方式:

    • 使用类的无参构造函数

    • 使用静态工厂创建

      在类中创建静态方法,返回类对象

       <beanid="bean2"class="com.liyiandxuegang.bean.Bean2Factory"factory-method="getBean2" />
      publicclassBean2 {
      publicvoidadd() {
      System.out.println("Bean 2 ------ Add");
      }
      }
      publicclassBean2Factory {
      // static methodpublicstaticBean2getBean2() {
      returnnewBean2();
      }
      }
      @TestpublicvoidtestStaticFactory() {
      // load ApplicationContextapplicationContext = newClassPathXmlApplicationContext("bean1.xml");
      Bean2bean2 = (Bean2) applicationContext.getBean("bean2");
      bean2.add();
      }
      
    • 使用实例工厂创建()

      创建一个不是静态的方法,,返回类的对象

       <!-- Createfactoryobject -->
      <beanid="bean3Factory"class="com.liyiandxuegang.bean.Bean3Factory" />
      <beanid="bean3"factory-bean="bean3Factory"factory-method="getBean3" />

    Bean tags property

    • id (name can be anything)

    • class: class qualified path

    • name: same as id, but id can't have special chars.

    • scope: singleton(default), prototype, request, session, globalSession: (ssl)

    属性注入:设置类的成员变量值

    Basic 方式:

    1. 有参构造函数
    publicclassUser{
    privateStringname;
    publicUser(Stringname) {
    this.name = name;
    }
    }
    Useruser = newUser("abcde");
    1. 使用set方法注入
    publicclassUser{
    privateStringname;
    publicvoidsetName(Stringname) {
    this.name = name;
    }
    }
    Useruser = newUser();
    user.setName("abcde");
    1. 使用接口的方法
    publicinterfaceDao {
    publicvoidassignVal(Stringname);
    }
    publicclassDaoImplimplementsDao {
    privateStringname;
    publicvoidassignVal(Stringname) {
    this.name = name;
    }
    }

    Sping method:

    1. set method(*)
    <!-- Use set method to inject property value -->
    <beanid="book"class="com.liyiandxuegang.property.Book">
    <!-- set value -->
    <propertyname="bookName"value="Test Value 2" />
    </bean>
    1. Constructor method
    // bean.xml 
    <!-- Useconstructortoinjectpropertyvalue -->
    <beanid="propertyDemo1"class="com.liyiandxuegang.property.PropertyDemo1">
    <!-- Injectvalue -->
    <constructor-argname="userName"value="Test Value" />
    </bean>
    // PropertyDemo1.javapublicclassPropertyDemo1 {
    privateStringuserName; publicPropertyDemo1(StringuserName) {
    this.userName = userName;
    }
    publicvoidtest1() {
    System.out.println("demo1--------test1()-------" + userName);
    }
    }
    // TestIoC.java@TestpublicvoidtestDemo1() {
    ApplicationContextapplicationContext = newClassPathXmlApplicationContext("bean1.xml");
    PropertyDemo1propertyDemo1 = (PropertyDemo1) applicationContext.getBean("propertyDemo1");
    propertyDemo1.test1();
    }

    ###注入对象类型的属性

    1. Create class (Servcie and Dao)
    • 在Service里面把dao作为类型属性;

    • 生成dao类型属性的set方法

    //1. Define a UserDao fieldprivateUserDaouserDao; //2. generate setmethodpublicvoidsetUserDao(UserDaouserDao) {
    this.userDao = userDao;
    }
    • 在配置文件中完成这个关系
    <!-- 注入对象类型的属性 --><!-- 1. 配置Service和Dao的对象 -->
    <beanid="userDao"class="com.liyiandxuegang.ioc.UserDao" />
    <beanid="userService"class="com.liyiandxuegang.ioc.UserService">
    <!-- Inject dao obj  name: service类里面属性的名称 ref: dao配置bean标签的id值-->
    <propertyname="userDao"ref="userDao"></property>
    </bean>
    • Test
    @TestpublicvoidtestUserService() {
    ApplicationContextapplicationContext = newClassPathXmlApplicationContext("bean1.xml");
    UserServiceuserService = (UserService) applicationContext.getBean("userService");
    userService.addService();
    }

    Namespace Inject

    <beansxmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!-- Use P namespace inject -->
    <beanid="person"class="com.liyiandxuegang.property.Person"p:pname="Name Value" />

    Complicated data type

    • Array, List, Map, Properties

    See the example:

    <!-- Inject complicated data value -->
    <beanid="personComplicated"class="com.liyiandxuegang.property.Person">
    <!-- array -->
    <propertyname="arraysStrings">
    <list>
    <value>Eric</value>
    <value>Mike</value>
    <value>Jim</value>
    </list>
    </property>
    <propertyname="list">
    <list>
    <value>Eric List</value>
    <value>Mike List</value>
    <value>Jim List</value>
    </list>
    </property>
    <propertyname="map">
    <map>
    <entrykey="aa"value="Eric aa" />
    <entrykey="bb"value="Mike BB" />
    </map>
    </property>
    <propertyname="properties">
    <props>
    <propkey="driverClass">com.mysql.jdbc.Driver</prop>
    <propkey="username">root</prop>
    </props>
    </property>
    </bean>

    Inside Person.java, we have all the set method defined.

    IoC and DI (Data Injection)

    IOC:控制反转,把对象创建交个spring进行配置。

    DI:依赖注入,向类中属性,设置属性值。

    关系: 依赖注入不能单独存在,需要在IOC基础上完成操作。

    Spring如何整合web项目

    • Loading spring configuration file use lots of resources.???
    ApplicationContextapplicationContext = newClassPathXmlApplicationContext("bean1.xml");

    ##Solution?

    把加载配置文件和创建对象过程,在服务器启动时候完成。

    How (base tech)?

    • ServletContext Object

    • Listener Object

    Steps to load spring objects

    • 在服务器启动时,为每个项目创建ServletContext对象,

    • 在ServletContext对象创建时,使用监听器可以监听到ServletContext对象在创建

    • 使用监听器听到ServletContext对象创建时,加载spring的配置文件,把配置文件配置对象创建。

    • 把创建出来的对象方法ServletContext的域对象里面

    • 获取对象时,到ServletContext域得到

Spring的bean管理(注解)

注解

  1. 代码里特殊的标记,使用注解也可以完成一些功能。

  2. 注解写法:@注解名称(属性名称=属性值)

  3. 注解可以使用在类上面,方法上面和属性上面

注解 (Steps) - Create class

  • import spring-aop.jar

  • Configure xml

<!-- define the package to scan -->
<context:component-scanbase-package="com.liyiandxuegang.anno" />

Then add @annotation above the class or field, or function

@Component(value="user") // <bean id="user" class="" />publicclassUser {
publicvoidannoAdd() {
System.out.println("anno Add...."); }
}

There are four annotations in Spring:

  • @Component [as component]

  • @Controller [Web]

  • @Service [Service]

  • @Repository: [Persistence]

功能相同,都是用来创建对象,用来将来对功能的扩展。

###但是控制类的作用范围:scope

@Component(value="user") // <bean id="user" class="" />@Scope(value="prototype")
publicclassUser {
publicvoidannoAdd() {
System.out.println("anno Add...."); }
}

注解方式注入属性

  • Create class obj

Create UserDao and UserService obje

@Component(value="userDao")
publicclassUserDao {
publicvoidadd() {
System.out.println("dao........add");
}
}
@Service(value="userService")
publicclassUserService {
// define the field of userDao@Autowired//自动注入的方法,找类的名字来注入类属性 (1)privateUserDaouserDao;
// Resource second way: but this time, the value of name should be the same as the objects.@Resource(name="userDao2")
privateUserDao2userDao2; publicvoidadd() {
System.out.println("Service.add ========");
userDao.add();
}
}

Use @Resource should be good.

Configuration + Annotation

  1. 创建对象操作使用配置文件方式实现;

  2. 注入属性的操作使用注解方式实现。

Suppose, we have three classes, BookService, BookDao.class, OrdersDao.class

In xml file,

 <context:component-scanbase-package="com.liyiandxuegang.xmlanno" />
<beanid="bookService"class="com.liyiandxuegang.xmlanno.BookService" /> <!--BookService bookService  <bean id="ordersDao" class="com.liyiandxuegang.xmlanno.OrdersDao" /> <!--OrdersDao ordersDao-->
<beanid="bookDao"class="com.liyiandxuegang.xmlanno.BookDao" /> <!--BookDao bookDao-->

In BookService.java file

publicclassBookService {
@Resource(name="bookDao")
privateBookDaobookDao;
@Resource(name="ordersDao")
privateOrdersDaoordersDao;
publicvoidadd() {
System.out.println("bookService ..... add");
bookDao.book();
ordersDao.order();
}
}

Then, we can test it, use the Bean to create the class.

ApplicationContextapplicationContext = newClassPathXmlApplicationContext("bean3.xml");
BookServicebookService = (BookService)applicationContext.getBean("bookService");

AOP (Aspect-Oriented Programming) 面向切面编程

Concept: 扩展功能不修改源代码实现。采用横向抽取机制,取代了传统纵向继承体系重复性代码(实际就是类的继承).

publicclassUser{
// Add userpublicvoidadd(Useruser) {
// code ...
}
}
// extends the function// add user, then add logging function.

纵向体系的问题:比如父类方法名称发生了变化,在子类调用的方法也需要变化。

横向抽取机制

底层使用:动态代理方式实现

  • One way (with inteface)
publicinterfaceDao{
publicvoidadd();
}
[使用动态代理方式创建接口实现代理对象]
publicclassDaoImplimplementsDao{
publicvoidadd() {
// code ....
}
}
// 增强add方法,创建和DaoImpl类平级对象,这个对象不是真正的对象,代理对象实现和DaoImpl相同的功能。// Use JDK dynamic proxy.
  • Second way (without interface) 使用cglib动态代理,没有接口
// user classpublicclassUser{
publicvoidadd() {
}
}
// 动态代理实现, 创建User类的子类的代理对象// 在子类中也可以调用父类的方法,完成增强

AOP Operation Terms

  1. Pointcut

  2. Advice:通知或者增强

前置通知:在方法执行之前,执行

后置通知:在方法之后执行

异常通知:方法出现异常之后

最终通知:在后置之后执行

环绕通知:在方法之前和之后来执行。

  1. Aspect: 切面

把增强应用到具体的方法上,这个过程称为切面。

// Basic classpublicclassUser{
publicvoidadd() {}
publicvoidupdate() {}
publicvoiddelete() {}
publicvoidfindAll() {}
}
// 连接点Jointpoint:类里面那些方法可以被增强,这些方法称为连接点。// 切入点Aspectpoint:在类里面可以有很多的方法增强,比如实际操作中,只是增强了类中add方法和update方法,实际增强的方法称为切入点。// Advice: 通知或者增强

Spring 的AOP操作

  1. 在spring里面进行AOP操作,使用AspectJ介绍

Spring 2.0, add AspectJ plugin.

  1. 使用aspectJ实现AOP操作,有两种方式:

*基于AspectJ的xml配置方式

*基于AspectJ的注解方式

AOP preparation

  1. Import basic jars, and import aop jars,

  2. Create spring xml, import aop schema.

Use Expression to configuration aspect point.

Mainly used expressions:

  • execution(public|private|* com.liyiandxuegang.aop.Book.add(..))

  • execution(* com.liyiandxuegang.aop.Book.*(..))

  • execution(* .(...))

execution( save*(..)): the methods with save starting.

How to configure? Read the following code:

<!-- 配置对象 -->
<beanid="book"class="com.liyiandxuegang.aop.Book" />
<beanid="myBook"class="com.liyiandxuegang.aop.MyBook" />
<!-- 配置aop操作 -->
<aop:config>
<!-- 1. 配置切入点 -->
<aop:pointcutexpression="execution(* com.liyiandxuegang.aop.Book.*(..))"id="pointcut1" />
<!-- 2. 配置切面  把增强用到方法上-->
<aop:aspectref="myBook">
<!-- 配置增强的类型  method: 增强的类中使用那个方法作为前置增强-->
<aop:beforemethod="before1"pointcut-ref="pointcut1" />
</aop:aspect>
</aop:config>

In the code level, we don't need to do anything different. The only thing you need to do is in the xml file.

<!-- 配置对象 -->
<beanid="bookaop"class="com.liyiandxuegang.aop.Book" />
<beanid="myBookaop"class="com.liyiandxuegang.aop.MyBook" />
<!-- 配置aop操作 -->
<aop:config>
<!-- 1. 配置切入点 -->
<aop:pointcutexpression="execution(* com.liyiandxuegang.aop.Book.*(..))"id="pointcut1"></aop:pointcut>
<!-- 2. 配置切面  把增强用到方法上-->
<aop:aspectref="myBookaop">
<!-- 配置增强的类型  method: 增强的类中使用那个方法作为前置增强-->
<aop:beforemethod="before1"pointcut-ref="pointcut1"></aop:before>
<aop:after-returningmethod="after"pointcut-ref="pointcut1"/>
<aop:aroundmethod="around"pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>

In around method, we need to call ProceedingJoinPoint method for function call.

log4j Introduciton

  • 日志的一个工具,通过log4j能够看到程序中更详细的信息。经常使用log4j查看日志

  • 导入log4j的jar包

  • 复制log4j的配置文件, 复制到src目录下。

Spring 整合 web项目 15. 15-spring整合web项目

  1. action 调用service, service调用dao, 需要使用struts2的内容。

About

Learning how to use Spring framework.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages