Spring 教程01
spring-1 1. Xml <!-- \src\beans-annotation.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" 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-4.0.xsd"> <!-- 配置自动扫描的包: 需要加入 aop 对应的 jar 包 --> <context:component-scan base-package="com.atguigu.spring.annotation.generic"></context:component-scan> </beans> <!-- \src\beans-auto.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" 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-4.0.xsd"> <!-- 自动装配: 只声明 bean, 而把 bean 之间的关系交给 IOC 容器来完成 --> <!-- byType: 根据类型进行自动装配. 但要求 IOC 容器中只有一个类型对应的 bean, 若有多个则无法完成自动装配. byName: 若属性名和某一个 bean 的 id 名一致, 即可完成自动装配. 若没有 id 一致的, 则无法完成自动装配 --> <!-- 在使用 XML 配置时, 自动转配用的不多. 但在基于 注解 的配置时, 自动装配使用的较多. --> <bean id="dao" class="com.atguigu.spring.ref.Dao"> <property name="dataSource" value="C3P0"></property> </bean> <!-- 默认情况下 bean 是单例的! --> <!-- 但有的时候, bean 就不能使单例的. 例如: Struts2 的 Action 就不是单例的! 可以通过 scope 属性来指定 bean 的作用域 --> <!-- prototype: 原型的. 每次调用 getBean 方法都会返回一个新的 bean. 且在第一次调用 getBean 方法时才创建实例 singleton: 单例的. 每次调用 getBean 方法都会返回同一个 bean. 且在 IOC 容器初始化时即创建 bean 的实例. 默认值 --> <bean id="dao2" class="com.atguigu.spring.ref.Dao" scope="prototype"></bean> <bean id="service" class="com.atguigu.spring.ref.Service" autowire="byName"></bean> <bean id="action" class="com.atguigu.spring.ref.Action" autowire="byType"></bean> <!-- 导入外部的资源文件 --> <context:property-placeholder location="classpath:db.properties" /> <!-- 配置数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <property name="initialPoolSize" value="${jdbc.initPoolSize}"></property> <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property> </bean> <!-- 测试 SpEL: 可以为属性进行动态的赋值(了解) --> <bean id="girl" class="com.atguigu.spring.helloworld.User"> <property name="userName" value="周迅"></property> </bean> <bean id="boy" class="com.atguigu.spring.helloworld.User" init-method="init" destroy-method="destroy"> <property name="userName" value="高胜远"></property> <property name="wifeName" value="#{girl.userName}"></property> </bean> <!-- 配置 bean 后置处理器: 不需要配置 id 属性, IOC 容器会识别到他是一个 bean 后置处理器, 并调用其方法 --> <bean class="com.atguigu.spring.ref.MyBeanPostProcessor"></bean> <!-- 通过工厂方法的方式来配置 bean --> <!-- 1. 通过静态工厂方法: 一个类中有一个静态方法, 可以返回一个类的实例(了解) --> <!-- 在 class 中指定静态工厂方法的全类名, 在 factory-method 中指定静态工厂方法的方法名 --> <bean id="dateFormat" class="java.text.DateFormat" factory-method="getDateInstance"> <!-- 可以通过 constructor-arg 子节点为静态工厂方法指定参数 --> <constructor-arg value="2"></constructor-arg> </bean> <!-- 2. 实例工厂方法: 先需要创建工厂对象, 再调用工厂的非静态方法返回实例(了解) --> <!-- ①. 创建工厂对应的 bean --> <bean id="simpleDateFormat" class="java.text.SimpleDateFormat"> <constructor-arg value="yyyy-MM-dd hh:mm:ss"></constructor-arg> </bean> <!-- ②. 有实例工厂方法来创建 bean 实例 --> <!-- factory-bean 指向工厂 bean, factory-method 指定工厂方法(了解) --> <bean id="datetime" factory-bean="simpleDateFormat" factory-method="parse"> <!-- 通过 constructor-arg 执行调用工厂方法需要传入的参数 --> <constructor-arg value="1990-12-12 12:12:12"></constructor-arg> </bean> <!-- 配置通过 FactroyBean 的方式来创建 bean 的实例(了解) --> <bean id="user" class="com.atguigu.spring.ref.UserBean"></bean> </beans> <!-- \src\beans.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:util="http://www.springframework.org/schema/util" 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 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 配置一个 bean --> <bean id="helloWorld" class="com.atguigu.spring.helloworld.HelloWorld"> <!-- 为属性赋值 --> <property name="user" value="Jerry"></property> </bean> <!-- 配置一个 bean --> <bean id="helloWorld2" class="com.atguigu.spring.helloworld.HelloWorld"> <!-- 为属性赋值 --> <!-- 通过属性注入: 通过 setter 方法注入属性值 --> <property name="user" value="Tom"></property> </bean> <!-- 通过构造器注入属性值 --> <bean id="helloWorld3" class="com.atguigu.spring.helloworld.HelloWorld"> <!-- 要求: 在 Bean 中必须有对应的构造器. --> <constructor-arg value="Mike"></constructor-arg> </bean> <!-- 若一个 bean 有多个构造器, 如何通过构造器来为 bean 的属性赋值 --> <!-- 可以根据 index 和 value 进行更加精确的定位. (了解) --> <bean id="car" class="com.atguigu.spring.helloworld.Car"> <constructor-arg value="KUGA" index="1"></constructor-arg> <constructor-arg value="ChangAnFord" index="0"></constructor-arg> <constructor-arg value="250000" type="float"></constructor-arg> </bean> <bean id="car2" class="com.atguigu.spring.helloworld.Car"> <constructor-arg value="ChangAnMazda"></constructor-arg> <!-- 若字面值中包含特殊字符, 则可以使用 DCDATA 来进行赋值. (了解) --> <constructor-arg> <value><![CDATA[<ATARZA>]]></value> </constructor-arg> <constructor-arg value="180" type="int"></constructor-arg> </bean> <!-- 配置 bean --> <bean id="dao5" class="com.atguigu.spring.ref.Dao"></bean> <bean id="service" class="com.atguigu.spring.ref.Service"> <!-- 通过 ref 属性值指定当前属性指向哪一个 bean! --> <property name="dao" ref="dao5"></property> </bean> <!-- 声明使用内部 bean --> <bean id="service2" class="com.atguigu.spring.ref.Service"> <property name="dao"> <!-- 内部 bean, 类似于匿名内部类对象. 不能被外部的 bean 来引用, 也没有必要设置 id 属性 --> <bean class="com.atguigu.spring.ref.Dao"> <property name="dataSource" value="c3p0"></property> </bean> </property> </bean> <bean id="action" class="com.atguigu.spring.ref.Action"> <property name="service" ref="service2"></property> <!-- 设置级联属性(了解) --> <property name="service.dao.dataSource" value="DBCP2"></property> </bean> <bean id="dao2" class="com.atguigu.spring.ref.Dao"> <!-- 为 Dao 的 dataSource 属性赋值为 null, 若某一个 bean 的属性值不是 null, 使用时需要为其设置为 null(了解) --> <property name="dataSource"> <null /> </property> </bean> <!-- 装配集合属性 --> <bean id="user" class="com.atguigu.spring.helloworld.User"> <property name="userName" value="Jack"></property> <property name="cars"> <!-- 使用 list 元素来装配集合属性 --> <list> <ref bean="car" /> <ref bean="car2" /> </list> </property> </bean> <!-- 声明集合类型的 bean --> <util:list id="cars"> <ref bean="car" /> <ref bean="car2" /> </util:list> <bean id="user2" class="com.atguigu.spring.helloworld.User"> <property name="userName" value="Rose"></property> <!-- 引用外部声明的 list --> <property name="cars" ref="cars"></property> </bean> <bean id="user3" class="com.atguigu.spring.helloworld.User" p:cars-ref="cars" p:userName="Titannic"></bean> <!-- bean 的配置能够继承吗 ? 使用 parent 来完成继承 --> <bean id="user4" parent="user" p:userName="Bob"></bean> <bean id="user6" parent="user" p:userName="维多利亚"></bean> <!-- 测试 depents-on --> <bean id="user5" parent="user" p:userName="Backham" depends-on="user6"></bean> </beans>
2. Properties # \src\db.properties jdbc.user=root jdbc.password=1230 jdbc.driverClass=com.mysql.jdbc.Driver jdbc.jdbcUrl=jdbc:mysql:///test jdbc.initPoolSize=5 jdbc.maxPoolSize=10 3. Java // \src\com\atguigu\spring\annotation\generic\BaseDao.java package com.atguigu.spring.annotation.generic; public class BaseDao<T> { public void save(T entity){ System.out.println("Save:" + entity); } } // \src\com\atguigu\spring\annotation\generic\BaseService.java package com.atguigu.spring.annotation.generic; import org.springframework.beans.factory.annotation.Autowired; public class BaseService<T> { @Autowired private BaseDao<T> dao; public void addNew(T entity){ System.out.println("addNew by " + dao); dao.save(entity); } } // \src\com\atguigu\spring\annotation\generic\Main.java package com.atguigu.spring.annotation.generic; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml"); UserService userService = (UserService) ctx.getBean("userService"); userService.addNew(new User()); RoleService roleService = (RoleService) ctx.getBean("roleService"); roleService.addNew(new Role()); } } // \src\com\atguigu\spring\annotation\generic\Role.java package com.atguigu.spring.annotation.generic; public class Role { } // \src\com\atguigu\spring\annotation\generic\RoleDao.java package com.atguigu.spring.annotation.generic; import org.springframework.stereotype.Repository; @Repository public class RoleDao extends BaseDao<Role>{ } // \src\com\atguigu\spring\annotation\generic\RoleService.java package com.atguigu.spring.annotation.generic; import org.springframework.stereotype.Service; @Service public class RoleService extends BaseService<Role>{ } // \src\com\atguigu\spring\annotation\generic\User.java package com.atguigu.spring.annotation.generic; public class User { } // \src\com\atguigu\spring\annotation\generic\UserDao.java package com.atguigu.spring.annotation.generic; import org.springframework.stereotype.Repository; @Repository public class UserDao extends BaseDao<User>{ } // \src\com\atguigu\spring\annotation\generic\UserService.java package com.atguigu.spring.annotation.generic; import org.springframework.stereotype.Service; //若注解没有指定 bean 的 id, 则类名第一个字母小写即为 bean 的 id @Service public class UserService extends BaseService<User>{ } // \src\com\atguigu\spring\annotation\Main.java package com.atguigu.spring.annotation; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-annotation.xml"); UserAction userAction = ctx.getBean(UserAction.class); userAction.execute(); } } // \src\com\atguigu\spring\annotation\UserAction.java package com.atguigu.spring.annotation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @Controller public class UserAction { @Autowired private UsreService usreService; public void execute(){ System.out.println("接受请求"); usreService.addNew(); } } // \src\com\atguigu\spring\annotation\UserDao.java package com.atguigu.spring.annotation; import org.springframework.stereotype.Service; @Service public class UserDao { public void save(){ System.out.println("保存新用户"); } } // \src\com\atguigu\spring\annotation\UsreService.java package com.atguigu.spring.annotation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UsreService { @Autowired private UserDao userDao; public void addNew(){ System.out.println("添加新用户"); userDao.save(); } } // \src\com\atguigu\spring\helloworld\Car.java package com.atguigu.spring.helloworld; public class Car { private String company; private String brand; private int maxSpeed; private float price; public Car(String company, String brand, float price) { super(); this.company = company; this.brand = brand; this.price = price; } public Car(String company, String brand, int maxSpeed) { super(); this.company = company; this.brand = brand; this.maxSpeed = maxSpeed; } public Car(String company, String brand, int maxSpeed, float price) { super(); this.company = company; this.brand = brand; this.maxSpeed = maxSpeed; this.price = price; } @Override public String toString() { return "Car [company=" + company + ", brand=" + brand + ", maxSpeed=" + maxSpeed + ", price=" + price + "]"; } } // \src\com\atguigu\spring\helloworld\HelloWorld.java package com.atguigu.spring.helloworld; public class HelloWorld { private String user; public HelloWorld() { System.out.println("HelloWorld's constructor..."); } public void setUser(String user) { System.out.println("setUser:" + user); this.user = user; } public HelloWorld(String user) { this.user = user; } public void hello(){ System.out.println("Hello: " + user); } } // \src\com\atguigu\spring\helloworld\Main.java package com.atguigu.spring.helloworld; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { // HelloWorld helloWorld = new HelloWorld(); // helloWorld.setUser("Tom"); // helloWorld.hello(); //1. 创建 Spring 的 IOC 容器 ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); //2. 从 IOC 容器中获取 bean 的实例 HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld3"); //根据类型来获取 bean 的实例: 要求在 IOC 容器中只有一个与之类型匹配的 bean, 若有多个则会抛出异常. //一般情况下, 该方法可用, 因为一般情况下, 在一个 IOC 容器中一个类型对应的 bean 也只有一个. // HelloWorld helloWorld1 = ctx.getBean(HelloWorld.class); //3. 使用 bean helloWorld.hello(); Car car = (Car) ctx.getBean("car"); System.out.println(car); Car car2 = (Car) ctx.getBean("car2"); System.out.println(car2); //4. 测试使用集合属性 User user = (User) ctx.getBean("user5"); System.out.println(user); } } // \src\com\atguigu\spring\helloworld\User.java package com.atguigu.spring.helloworld; import java.util.List; public class User { private String userName; private List<Car> cars; private String wifeName; public String getWifeName() { return wifeName; } public void setWifeName(String wifeName) { System.out.println("setWifhName: " + wifeName); this.wifeName = wifeName; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public List<Car> getCars() { return cars; } public void setCars(List<Car> cars) { this.cars = cars; } public User() { System.out.println("User's Construtor..."); } @Override public String toString() { return "User [userName=" + userName + ", cars=" + cars + "]"; } public void init(){ System.out.println("init method..."); } public void destroy(){ System.out.println("destroy method..."); } } // \src\com\atguigu\spring\ref\Action.java package com.atguigu.spring.ref; public class Action { private Service service; public void setService(Service service) { this.service = service; } public Service getService() { return service; } public void execute(){ System.out.println("Action's execute..."); service.save(); } } // \src\com\atguigu\spring\ref\Dao.java package com.atguigu.spring.ref; public class Dao { private String dataSource = "dbcp"; public void setDataSource(String dataSource) { this.dataSource = dataSource; } public void save(){ System.out.println("save by " + dataSource); } public Dao() { System.out.println("Dao's Constructor..."); } } // \src\com\atguigu\spring\ref\Main.java package com.atguigu.spring.ref; import java.sql.SQLException; import java.text.DateFormat; import java.util.Date; import javax.sql.DataSource; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.atguigu.spring.helloworld.User; public class Main { public static void main(String[] args) throws SQLException { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans-auto.xml"); Action action = ctx.getBean(Action.class); action.execute(); //测试 bean 的作用域 Dao dao1 = (Dao) ctx.getBean("dao2"); Dao dao2 = (Dao) ctx.getBean("dao2"); System.out.println(dao1 == dao2); //测试使用外部属性文件 DataSource dataSource = (DataSource) ctx.getBean("dataSource"); System.out.println(dataSource.getConnection()); //测试 spEL User boy = (User) ctx.getBean("boy"); System.out.println(boy.getUserName() + ":" + boy.getWifeName()); // DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.FULL); DateFormat dateFormat = (DateFormat) ctx.getBean("dateFormat"); System.out.println(dateFormat.format(new Date())); Date date = (Date) ctx.getBean("datetime"); System.out.println(date); User user = (User) ctx.getBean("user"); System.out.println(user); ctx.close(); } } // \src\com\atguigu\spring\ref\MyBeanPostProcessor.java package com.atguigu.spring.ref; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import com.atguigu.spring.helloworld.User; public class MyBeanPostProcessor implements BeanPostProcessor { //该方法在 init 方法之后被调用 @Override public Object postProcessAfterInitialization(Object arg0, String arg1) throws BeansException { if(arg1.equals("boy")){ System.out.println("postProcessAfterInitialization..." + arg0 + "," + arg1); User user = (User) arg0; user.setUserName("李大齐"); } return arg0; } //该方法在 init 方法之前被调用 //可以工作返回的对象来决定最终返回给 getBean 方法的对象是哪一个, 属性值是什么 /** * @param arg0: 实际要返回的对象 * @param arg1: bean 的 id 值 */ @Override public Object postProcessBeforeInitialization(Object arg0, String arg1) throws BeansException { if(arg1.equals("boy")) System.out.println("postProcessBeforeInitialization..." + arg0 + "," + arg1); return arg0; } } // \src\com\atguigu\spring\ref\Service.java package com.atguigu.spring.ref; public class Service { private Dao dao; public void setDao(Dao dao) { this.dao = dao; } public Dao getDao() { return dao; } public void save(){ System.out.println("Service's save"); dao.save(); } } // \src\com\atguigu\spring\ref\UserBean.java package com.atguigu.spring.ref; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.FactoryBean; import com.atguigu.spring.helloworld.Car; import com.atguigu.spring.helloworld.User; public class UserBean implements FactoryBean<User>{ /** * 返回的 bean 的实例 */ @Override public User getObject() throws Exception { User user = new User(); user.setUserName("abc"); user.setWifeName("ABC"); List<Car> cars = new ArrayList<>(); cars.add(new Car("ShangHai", "BuiKe", 180, 300000)); cars.add(new Car("ShangHai", "CRUZE", 130, 150000)); user.setCars(cars); return user; } /** * 返回的 bean 的类型 */ @Override public Class<?> getObjectType() { return User.class; } /** * 返回的 bean 是否为单例的 */ @Override public boolean isSingleton() { return true; } }