Spring Framework
- Introduction
- Inversion of Control:
- Usages
- Spring Bean Factory
- ApplicationContext and Property initialization
- Injection
- Constructor Injection
- Object Injection, Inner Beans, Aliases and idref
- Initializing Collections
- Autowiring
- Bean Scope
- ApplicationAware&BeanNameAware
- Bean Definition Inheritance
- Lifecycle Callbacks
- BeanPostProcessor
- BeanFactoryPostProcessor
- Coding to Interface
- Annotations
- The Required Annotation
- The Autowired Annotation
- JSR-250 Annotations
- Component and Stereotype Annotations
- Using MessageSource To Get Text From Property Files
- Event Handling in Spring
- Usages
- Spring MVC
- MVC Models
- 从动态代理到SpringAOP
- 什么是动态代理
- 动态代理的实现方式
- jdkproxy
- CGLIB
- SpringAOP中动态代理的体现
Introduction

Inversion of Control:
控制指谁来控制对象的创建,传统的应用程序对象的创建是由程序本身控制的,使用 Spring 后是由 Spring 来创建的。正转指程序来创建对象,反转指程序本身不去创建对象,而变为被动接受的对象。
- ioc是一种编程思想。由主动编程变为被动接收
- ioc的实现是通过ioc容器来实现的。
- ioc容器——BeanFactory。
🔗:IoC容器(Ioc : Inversion of control)和Dependency Injection模式
Usages
Spring Bean Factory
使用spring framework提供的基本的工厂特性创建对象,该对象的生命周期由spring管理。对象工厂所做的是从配置文件(bluedprint:spring.xml)中读取该对象工厂必须创建的所有对象。
public class Triangle {
public void draw() {
System.out.println("Triangle drawn");
}
}
public class DrawingApp {
public static void main(String[] args) {
//Triangle triangle = new Triangle();
//deprecated
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("spring.xml"));
Triangle triangle = (Triangle) factory.getBean("triangle");
triangle.draw();
}
}
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="triangle" class="com.iamwyj.beanfactory.Triangle" />
</beans>
ApplicationContext and Property initialization
ApplicationContext包含👆的Beanfactory所有的特性之外还有其他特性,例如AOP
public class Triangle {
private String type;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public void draw() {
System.out.println(this.getType() + " triangle drawn");
}
}
public class DrawingApp {
public static void main(String[] args) {
// spring.xml置于src下
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Triangle triangle = (Triangle) context.getBean("triangle");
triangle.draw();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="triangle" class="com.iamwyj.applicationcontext.Triangle">
<!-- Property initialization -->
<!-- Setter Injection -->
<property name="type" value="Equilateral"/>
</bean>
</beans>
Injection
Constructor Injection
public class Triangle {
private String type;
private int height;
public Triangle(String type) {
this.type = type;
}
public Triangle(int height) {
this.height = height;
}
public Triangle(String type, int height) {
this.type = type;
this.height = height;
}
public String getType() {
return type;
}
public int getHeight() {
return height;
}
public void draw() {
System.out.println(this.getType() + " triangle drawn of height " + this.getHeight());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="triangle" class="com.iamwyj.constructorinjection.Triangle">
<!-- <constructor-arg value="Equilateral" /> -->
<!-- <constructor-arg type="int" value="20"/> -->
<!-- <constructor-arg type="java.lang.String" value="20"/> -->
<constructor-arg index="0" value="Equilateral"/>
<constructor-arg index="1" value="20"/>
</bean>
</beans>
Object Injection, Inner Beans, Aliases and idref
public class Point {
private int x;
private int y;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
public class Triangle {
private Point pointA;
private Point pointB;
private Point pointC;
public Point getPointA() {
return pointA;
}
public void setPointA(Point pointA) {
this.pointA = pointA;
}
public Point getPointB() {
return pointB;
}
public void setPointB(Point pointB) {
this.pointB = pointB;
}
public Point getPointC() {
return pointC;
}
public void setPointC(Point pointC) {
this.pointC = pointC;
}
public void draw() {
System.out.println("Point A = ("+this.getPointA().getX()+","+this.getPointA().getY()+")");
System.out.println("Point B = ("+this.getPointB().getX()+","+this.getPointB().getY()+")");
System.out.println("Point C = ("+this.getPointC().getX()+","+this.getPointC().getY()+")");
}
}
public class DrawingApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Triangle triangle = (Triangle) context.getBean("triangle-alias");
triangle.draw();
}
}
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="triangle" class="com.iamwyj.injectobjects.Triangle"
name="triangle-name">
<property name="pointA" ref="point0" />
<property name="pointB">
<!-- inner bean -->
<bean class="com.iamwyj.injectobjects.Point">
<property name="x" value="-20" />
<property name="y" value="0" />
</bean>
</property>
<property name="pointC" ref="point2" />
</bean>
<!-- Aliases -->
<alias name="triangle" alias="triangle-alias" />
<bean id="point0" class="com.iamwyj.injectobjects.Point">
<property name="x" value="0" />
<property name="y" value="0" />
</bean>
<bean id="point2" class="com.iamwyj.injectobjects.Point">
<property name="x" value="0" />
<property name="y" value="20" />
</bean>
<!-- <idref/>make sure that there is a bean with id... -->
</beans>
Initializing Collections
import java.util.List;
public class Triangle {
private List<Point> points;
public List<Point> getPoints() {
return points;
}
public void setPoints(List<Point> points) {
this.points = points;
}
public void draw() {
for(Point point:points)
System.out.println("Point = ("+point.getX()+","+point.getY()+")");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="triangle" class="com.iamwyj.collections.Triangle">
<property name="points">
<list>
<ref bean = "point0" />
<ref bean = "point1" />
<ref bean = "point2" />
</list>
</property>
</bean>
<bean id="point0" class="com.iamwyj.collections.Point">
<property name="x" value="0" />
<property name="y" value="0" />
</bean>
<bean id="point1" class="com.iamwyj.collections.Point">
<property name="x" value="-20" />
<property name="y" value="0" />
</bean>
<bean id="point2" class="com.iamwyj.collections.Point">
<property name="x" value="0" />
<property name="y" value="20" />
</bean>
</beans>
Autowiring
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<!-- scope默认为singleton -->
<!-- byname, byType, constructor -->
<bean id="triangle" class="com.iamwyj.autowiringandscope.Triangle" autowire="byName" scope="prototype"/>
<bean id="pointA" class="com.iamwyj.autowiringandscope.Point">
<property name="x" value="0" />
<property name="y" value="0" />
</bean>
<bean id="pointB" class="com.iamwyj.autowiringandscope.Point">
<property name="x" value="-20" />
<property name="y" value="0" />
</bean>
<bean id="pointC" class="com.iamwyj.autowiringandscope.Point">
<property name="x" value="0" />
<property name="y" value="20" />
</bean>
</beans>
Bean Scope
- Singleton(和设计模式中所说的singleton不完全相同) - Only once per Spring container
- Prototype - New bean created with every request and reference。
- Web-aware Context Bean Scope
- Request - New bean per servlet request
- Session - New bean per session
- Globle Session - New bean per global HTTP session(portlet context) 默认为Singleton,所以spring容器中的bean默认在容器初始化的时候(spring load time)就创建了,而非在调用getBean方法时调用,调用此方法时,spring容器直接将创建好的bean返回给它。但是如果将scope设置为prototype的话,则每次等到调用getBean方法时才调用,并且每次都创建新的实例。
ApplicationAware&BeanNameAware
通过实现ApplicationAware接口方法可以获得ApplicationContext对象; 通过实现BeanNameAware接口方法可以获得该Bean在Spring.xml配置文件中配置的name;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class Triangle implements ApplicationContextAware, BeanNameAware {
private Point pointA;
private Point pointB;
private Point pointC;
private ApplicationContext context = null;
public Point getPointA() {
return pointA;
}
public void setPointA(Point pointA) {
this.pointA = pointA;
}
public Point getPointB() {
return pointB;
}
public void setPointB(Point pointB) {
this.pointB = pointB;
}
public Point getPointC() {
return pointC;
}
public void setPointC(Point pointC) {
this.pointC = pointC;
}
public void draw() {
System.out.println("Point A = ("+this.getPointA().getX()+","+this.getPointA().getY()+")");
System.out.println("Point B = ("+this.getPointB().getX()+","+this.getPointB().getY()+")");
System.out.println("Point C = ("+this.getPointC().getX()+","+this.getPointC().getY()+")");
}
@Override
public void setBeanName(String beanName) {
System.out.println("Bean name is "+beanName);
}
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.context = context;
}
}
Bean Definition Inheritance
import java.util.List;
import com.iamwyj.beaninheritance.Point;
public class Triangle {
private List<Point> points;
public List<Point> getPoints() {
return points;
}
public void setPoints(List<Point> points) {
this.points = points;
}
public void draw() {
for (Point point : points)
System.out.println("Point = (" + point.getX() + "," + point.getY() + ")");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<!-- abstract告诉spring不要创建bean,这是一个模版(template) -->
<bean id="parenttriangle" class="com.iamwyj.beaninheritance.Triangle"
abstract="true">
<property name="points">
<list>
<ref bean="pointA" />
</list>
</property>
</bean>
<bean id="triangle1" class="com.iamwyj.beaninheritance.Triangle"
parent="parenttriangle">
<property name="points">
<!-- merge的意思是合并继承的集合中的值,否则会覆盖 -->
<list merge="true">
<ref bean="pointB" />
</list>
</property>
</bean>
<bean id="pointA" class="com.iamwyj.beaninheritance.Point">
<property name="x" value="0" />
<property name="y" value="0" />
</bean>
<bean id="pointB" class="com.iamwyj.beaninheritance.Point">
<property name="x" value="-20" />
<property name="y" value="0" />
</bean>
<bean id="pointC" class="com.iamwyj.beaninheritance.Point">
<property name="x" value="0" />
<property name="y" value="20" />
</bean>
</beans>
Lifecycle Callbacks
package com.iamwyj.lifecyclecallback;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class Triangle implements InitializingBean, DisposableBean{
private Point pointA;
private Point pointB;
private Point pointC;
public Point getPointA() {
return pointA;
}
public void setPointA(Point pointA) {
this.pointA = pointA;
}
public Point getPointB() {
return pointB;
}
public void setPointB(Point pointB) {
this.pointB = pointB;
}
public Point getPointC() {
return pointC;
}
public void setPointC(Point pointC) {
this.pointC = pointC;
}
public void draw() {
System.out.println("Point A = ("+this.getPointA().getX()+","+this.getPointA().getY()+")");
System.out.println("Point B = ("+this.getPointB().getX()+","+this.getPointB().getY()+")");
System.out.println("Point C = ("+this.getPointC().getX()+","+this.getPointC().getY()+")");
}
// 方式二通过在spring.xml文件中配置
public void myInit() {
System.out.println("My init method called for triangle");
}
public void myDestroy() {
System.out.println("My destroy method called for triangle");
}
// 方式一通过实现接口
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean init method called for triangle");
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean destroy method called for triangle");
}
}
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DrawingApp {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
context.registerShutdownHook();
Triangle triangle = (Triangle) context.getBean("triangle");
triangle.draw();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<!-- 全局配置 -->
<beans default-init-method="myInit" default-destroy-method="myDestroy">
<!-- 针对单个的bean -->
<!-- init-method="myInit" destroy-method="myDestroy" -->
<bean id="triangle" class="com.iamwyj.lifecyclecallback.Triangle">
<property name="pointA" ref="point0" />
<property name="pointB" ref="point1" />
<property name="pointC" ref="point2" />
</bean>
<bean id="point0" class="com.iamwyj.lifecyclecallback.Point">
<property name="x" value="0" />
<property name="y" value="0" />
</bean>
<bean id="point1" class="com.iamwyj.lifecyclecallback.Point">
<property name="x" value="-20" />
<property name="y" value="0" />
</bean>
<bean id="point2" class="com.iamwyj.lifecyclecallback.Point">
<property name="x" value="0" />
<property name="y" value="20" />
</bean>
</beans>
BeanPostProcessor
package com.iamwyj.beanpostprocessor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class DisplayNameBeanPostProcessor implements BeanPostProcessor {
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("In after initialization method, bean is "+ beanName);
return bean;
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException{
System.out.println("In before initialization method, bean is "+ beanName);
return bean;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans default-init-method="myInit" default-destroy-method="myDestroy">
<bean id="triangle" class="com.iamwyj.beanpostprocessor.Triangle"> <!-- init-method="myInit" destroy-method="myDestroy" -->
<property name="pointA" ref="point0" />
<property name="pointB" ref="point1" />
<property name="pointC" ref="point2" />
</bean>
<bean id="point0" class="com.iamwyj.beanpostprocessor.Point">
<property name="x" value="0" />
<property name="y" value="0" />
</bean>
<bean id="point1" class="com.iamwyj.beanpostprocessor.Point">
<property name="x" value="-20" />
<property name="y" value="0" />
</bean>
<bean id="point2" class="com.iamwyj.beanpostprocessor.Point">
<property name="x" value="0" />
<property name="y" value="20" />
</bean>
<bean class="com.iamwyj.beanpostprocessor.DisplayNameBeanPostProcessor" />
</beans>
运行结果:

BeanFactoryPostProcessor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class MyBeanFactoryPP implements BeanFactoryPostProcessor{
// beanfactory初始之前时候执行
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("My bean factory post processor method is called.");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans default-init-method="myInit" default-destroy-method="myDestroy">
<bean id="triangle" class="com.iamwyj.beanfactorypostprocessor.Triangle"> <!-- init-method="myInit" destroy-method="myDestroy" -->
<property name="pointA" ref="point0" />
<property name="pointB" ref="point1" />
<property name="pointC" ref="point2" />
</bean>
<bean id="point0" class="com.iamwyj.beanfactorypostprocessor.Point">
<!-- property placeholder -->
<property name="x" value="${pointA.pointX}" />
<property name="y" value="${pointA.pointY}" />
</bean>
<bean id="point1" class="com.iamwyj.beanfactorypostprocessor.Point">
<property name="x" value="-20" />
<property name="y" value="0" />
</bean>
<bean id="point2" class="com.iamwyj.beanfactorypostprocessor.Point">
<property name="x" value="0" />
<property name="y" value="20" />
</bean>
<bean class="com.iamwyj.beanfactorypostprocessor.MyBeanFactoryPP" />
<!-- spring提供的bean factory post processor -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
<property name="locations" value="pointsconfig.properties" />
</bean>
</beans>
poinsconfig.properties
pointA.pointX=0
pointA.pointY=0
运行结果:

Coding to Interface
public class Point {
private int x;
private int y;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
public interface Shape {
public void draw();
}
public class Triangle implements Shape {
private Point pointA;
private Point pointB;
private Point pointC;
public Point getPointA() {
return pointA;
}
public void setPointA(Point pointA) {
this.pointA = pointA;
}
public Point getPointB() {
return pointB;
}
public void setPointB(Point pointB) {
this.pointB = pointB;
}
public Point getPointC() {
return pointC;
}
public void setPointC(Point pointC) {
this.pointC = pointC;
}
public void draw() {
System.out.println("Drawing Triangle");
System.out.println("Point A = ("+this.getPointA().getX()+","+this.getPointA().getY()+")");
System.out.println("Point B = ("+this.getPointB().getX()+","+this.getPointB().getY()+")");
System.out.println("Point C = ("+this.getPointC().getX()+","+this.getPointC().getY()+")");
}
}
public class Circle implements Shape{
private Point center;
public Point getCenter() {
return center;
}
public void setCenter(Point center) {
this.center = center;
}
@Override
public void draw() {
System.out.println("Drawing Circle");
System.out.println("Circle: Point is ("+center.getX()+","+center.getY()+")");
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DrawingApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Shape shape = (Shape) context.getBean("circle");
shape.draw();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="triangle" class="com.iamwyj.codingtointerface.Triangle">
<property name="pointA" ref="point0" />
<property name="pointB" ref="point1" />
<property name="pointC" ref="point2" />
</bean>
<bean id="circle" class="com.iamwyj.codingtointerface.Circle">
<property name="center" ref="point0" />
</bean>
<bean id="point0" class="com.iamwyj.codingtointerface.Point">
<property name="x" value="0" />
<property name="y" value="0" />
</bean>
<bean id="point1" class="com.iamwyj.codingtointerface.Point">
<property name="x" value="-20" />
<property name="y" value="0" />
</bean>
<bean id="point2" class="com.iamwyj.codingtointerface.Point">
<property name="x" value="0" />
<property name="y" value="20" />
</bean>
</beans>
Annotations
The Required Annotation
package com.iamwyj.annotation;
import org.springframework.beans.factory.annotation.Required;
public class Circle implements Shape{
private Point center;
public Point getCenter() {
return center;
}
@Required
public void setCenter(Point center) {
this.center = center;
}
@Override
public void draw() {
System.out.println("Drawing Circle");
System.out.println("Circle: Point is ("+center.getX()+","+center.getY()+")");
}
}
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean id="circle" class="com.iamwyj.annotation.Circle" />
<!-- @Required注解的bean processor -->
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
</beans>
The Autowired Annotation
package com.iamwyj.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class Circle implements Shape{
private Point center;
public Point getCenter() {
return center;
}
@Autowired
@Qualifier("circleRelated")
public void setCenter(Point center) {
this.center = center;
}
@Override
public void draw() {
System.out.println("Drawing Circle");
System.out.println("Circle: Point is ("+center.getX()+","+center.getY()+")");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- xml 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-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean id="circle" class="com.iamwyj.annotation.Circle" />
<bean id="point0" class="com.iamwyj.annotation.Point">
<qualifier value="circleRelated" />
<property name="x" value="0" />
<property name="y" value="0" />
</bean>
<bean id="center" class="com.iamwyj.annotation.Point">
<property name="x" value="-20" />
<property name="y" value="0" />
</bean>
<!-- @@Autowired注解 -->
<bean
class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />-->
<!-- 以上所有的关于注解的BeanPostProcessor的注册可以被以下快捷方式替代 -->
<context:annotation-config/>
</beans>
JSR-250 Annotations
package com.iamwyj.jsrannotation;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
public class Circle implements Shape {
private Point center;
public Point getCenter() {
return center;
}
@Resource(name = "point2")
// 如果不设置name值,会默认寻找名为center的bean进行注入
public void setCenter(Point center) {
this.center = center;
}
@PostConstruct
public void initializeCircle() {
System.out.println("Init of Circle");
}
@PreDestroy
public void destroyCircle() {
System.out.println("Destroy of Circle");
}
@Override
public void draw() {
System.out.println("Drawing Circle");
System.out.println("Circle: Point is (" + center.getX() + "," + center.getY() + ")");
}
}
package com.iamwyj.jsrannotation;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DrawingApp {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
context.registerShutdownHook();
Shape shape = (Shape) context.getBean("circle");
shape.draw();
}
}
/* Output:
* Init of Circle
* Drawing Circle
* Circle Point is: (20, 0)
* Destroy of Circle
*/
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean id="circle" class="com.iamwyj.jsrannotation.Circle" />
<bean id="point0" class="com.iamwyj.jsrannotation.Point">
<qualifier value="circleRelated" />
<property name="x" value="0" />
<property name="y" value="0" />
</bean>
<bean id="point1" class="com.iamwyj.jsrannotation.Point">
<property name="x" value="-20" />
<property name="y" value="0" />
</bean>
<bean id="point2" class="com.iamwyj.jsrannotation.Point">
<property name="x" value="0" />
<property name="y" value="20" />
</bean>
</beans>
Component and Stereotype Annotations
package com.iamwyj.stereotypeannotation;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
//@Component //generic object
//if marked as follows, spring will know what the class was doing.
//@Service
//@Repository //data object
@Controller
public class Circle implements Shape {
private Point center;
public Point getCenter() {
return center;
}
@Resource
public void setCenter(Point center) {
this.center = center;
}
@PostConstruct
public void initializeCircle() {
System.out.println("Init of Circle");
}
@PreDestroy
public void destroyCircle() {
System.out.println("Destroy of Circle");
}
@Override
public void draw() {
System.out.println("Drawing Circle");
System.out.println("Circle: Point is (" + center.getX() + "," + center.getY() + ")");
}
}
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config />
<bean id="triangle" class="com.iamwyj.stereotypeannotation.Triangle">
<property name="pointA" ref="point0" />
<property name="pointB" ref="point1" />
<property name="pointC" ref="point2" />
</bean>
<bean id="point0" class="com.iamwyj.stereotypeannotation.Point">
<qualifier value="circleRelated" />
<property name="x" value="0" />
<property name="y" value="0" />
</bean>
<bean id="point1" class="com.iamwyj.stereotypeannotation.Point">
<property name="x" value="-20" />
<property name="y" value="0" />
</bean>
<bean id="point2" class="com.iamwyj.stereotypeannotation.Point">
<property name="x" value="0" />
<property name="y" value="20" />
</bean>
<bean id="center" class="com.iamwyj.stereotypeannotation.Point">
<property name="x" value="6" />
<property name="y" value="20" />
</bean>
<context:component-scan base-package="com.iamwyj.stereotypeannotation"/>
</beans>
Using MessageSource To Get Text From Property Files
新建mymessage.properties文件
greeting=Hello!
drawing.circle=Drawing Circle!
drawing.point=Circle: Point is ({0},{1})
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config />
<bean id="point0" class="com.iamwyj.messagesource.Point">
<qualifier value="circleRelated" />
<property name="x" value="0" />
<property name="y" value="0" />
</bean>
<bean id="center" class="com.iamwyj.messagesource.Point">
<property name="x" value="6" />
<property name="y" value="20" />
</bean>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>mymessages</value>
</list>
</property>
</bean>
<context:component-scan base-package="com.iamwyj.messagesource"/>
</beans>
package com.iamwyj.messagesource;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
//@Component //generic object
//if marked as follows, spring will know what the class was doing.
//@Service
//@Repository //data object
@Controller
public class Circle implements Shape {
private Point center;
@Autowired
private MessageSource messageSource;
public MessageSource getMessageSource() {
return messageSource;
}
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
public Point getCenter() {
return center;
}
@Resource
public void setCenter(Point center) {
this.center = center;
}
@PostConstruct
public void initializeCircle() {
System.out.println("Init of Circle");
}
@PreDestroy
public void destroyCircle() {
System.out.println("Destroy of Circle");
}
@Override
public void draw() {
System.out.println(this.messageSource.getMessage("drawing.circle", null, "Default Drawing Message", null));
System.out.println(this.messageSource.getMessage("drawing.point", new Object[] {this.center.getX(),this.center.getY()}, "Default Points Message", null));
System.out.println(this.messageSource.getMessage("greeting", null, "Default Greeting", null));
}
}
Event Handling in Spring
package com.iamwyj.eventhandling;
import org.springframework.context.ApplicationEvent;
public class DrawEvent extends ApplicationEvent {
public DrawEvent(Object source) {
super(source);
// TODO Auto-generated constructor stub
}
public String toString() {
return "Draw Event Occured";
}
}
package com.iamwyj.eventhandling;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class MyEventListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println(event.toString());
}
}
package com.iamwyj.eventhandling;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
//@Component //generic object
//if marked as follows, spring will know what the class was doing.
//@Service
//@Repository //data object
@Controller
public class Circle implements Shape, ApplicationEventPublisherAware {
private Point center;
@Autowired
private MessageSource messageSource;
private ApplicationEventPublisher publisher;
public MessageSource getMessageSource() {
return messageSource;
}
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
public Point getCenter() {
return center;
}
@Resource
public void setCenter(Point center) {
this.center = center;
}
@PostConstruct
public void initializeCircle() {
System.out.println("Init of Circle");
}
@PreDestroy
public void destroyCircle() {
System.out.println("Destroy of Circle");
}
@Override
public void draw() {
System.out.println(this.messageSource.getMessage("drawing.circle", null, "Default Drawing Message", null));
System.out.println(this.messageSource.getMessage("drawing.point",
new Object[] { this.center.getX(), this.center.getY() }, "Default Points Message", null));
System.out.println(this.messageSource.getMessage("greeting", null, "Default Greeting", null));
DrawEvent drawEvent = new DrawEvent(this);
publisher.publishEvent(drawEvent);
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
}
Spring MVC
MVC设计思想:任何重定向都能解耦合

MVC Models
-
Model1:耦合太高

-
Model2:

-
C/S:模型层主动推送数据到视图
-
B/S:模型层不能推送数据到视图层
mvc框架要求:
- 将url映射到java类或java类的方法
- 封装用户提交的数据
- 处理请求——调用相关的业务处理封装响应的数据
- 将响应数据的数据进行渲染,jsp,html,freemaker等
从动态代理到SpringAOP
什么是动态代理
代理模式可以看作对调用目标的包装,这样对目标代码的调用不是直接发生的,而是通过代理完成,很多动态代理场景也可以看作是装饰器模式的应用。代理的目的可以让调用者与实现这解耦。动态代理是一种方便运行时动态构建代理、动态处理代理方法调用的机制,PRC的调用以及AOP都是基于动态代理,这也用到了设计模式中的代理模式,可以解决很多繁琐的重复编程,这一点在SpringAOP中可以体现,此处的动态表示代理类在运行时产生,而AspectJ对目标代码的生成则是在编译期编织。
动态代理的实现方式
实现动态代理的方式主要有Java自身提供的动态代理(基于反射)以及cglib(基于ASM,直接操作字节码),ASM框架是对字节码类库的封装。
jdkproxy
Java自身提供的动态代理由于是jdk本省支持的,依赖关系小,简化开发,易于维护,但需要调用者实现接口,此种方式具有侵入性。
代码使用示例:
public interface Hello {
void sayHello();
}
public class HelloImpl implements Hello {
@Override
public void sayHello() {
System.out.println("Hello World");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
//代理可看作是对调用目标的包装
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Invoking sayHello!");
Object result = method.invoke(target, args);
return result;
}
}
import java.lang.reflect.Proxy;
public class MyDynamicProxy {
public static void main(String[] args) {
HelloImpl hello = new HelloImpl();
MyInvocationHandler handler = new MyInvocationHandler(hello);
//构造代码实例
Hello proxyHello = (Hello) Proxy.newProxyInstance(HelloImpl.class.getClassLoader(), HelloImpl.class.getInterfaces(), handler);
//使用代理方法
proxyHello.sayHello();
}
}
//TODO 构造函数底层源码:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
CGLIB
cglib不需要限定调用者实现接口,也不必为其他相关类增加工作量,因此性能更高。
使用代码示例:
public class Person {
public String sayHello(String name) {
System.out.println("-- 正在执行sayHello方法 --");
//返回简单的字符串
return name + " Hello, cglib proxy";
}
public void eat(String food) {
System.out.println("我正在吃:" + food);
}
}
import org.springframework.cglib.proxy.Enhancer;
//此类会通过CGLIB来为Person生成代理类
public class PersonProxyFactory {
public static Person getAuthInstance() {
Enhancer en = new Enhancer();
//设置要代理的目标类
en.setSuperclass(Person.class);
//设置要代理的拦截器
en.setCallback(new AroundAdvice());
//生成代理类的实例
return (Person) en.create();
}
}
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
//先为 CGLIB 提供一个拦截器实现类
public class AroundAdvice implements MethodInterceptor {
@Override
public Object intercept(Object target, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("执行开始方法前,模拟开始事物...");
//执行目标方法,并保存目标方法执行后的返回值
Object rvt = methodProxy.invokeSuper(target, new String[]{"被改变的参数"});
System.out.println("执行目标方法之后,模拟结束事物...");
return rvt+ " 新增的内容";
}
}
public class Main {
public static void main(String[] args) {
Person person= PersonProxyFactory.getAuthInstance();
System.out.println(person.sayHello("孙悟空"));
person.eat("西瓜");
System.out.println(person.getClass());
}
}
SpringAOP中动态代理的体现
- 事物控制
- 动态代理
- 运行时动态生成一个java类