IOC:(Inversion(反转) Of Control):控制反转
DI:(Dependency Injection)依赖注入
<!--一个Bean标签可以注册一个组件(类、对象)-->
<!-- class:组件的全类名 id:唯一标识 -->
<bean id="person1" class="com.bean.Person">
<!--使用property标签为Person对象的属性赋值-->
<!-- name="" : 指定属性名 value="" :指定属性的值-->
<property name="personName" value="张三" ></property>
<property name="personAge" value="18" ></property>
</bean>
复制代码
public void test(){
//ApplicationContext 代表ioc容器
//ClassPathXmlApplicationContext:当前应用的xml配置文件在ClassPath下
//根据配置文件得到ioc容器对象
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
Person person = (Person)ioc.getBean("person1");
}
复制代码
<bean id="person1" class="com.bean.Person">
<property name="personName" value="张三" ></property>
<property name="personAge" value="18" ></property>
</bean>
<bean id="person2" class="com.bean.Person">
<property name="personName" value="小花" ></property>
<property name="personAge" value="18" ></property>
</bean>
复制代码
public void test(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
//如果ioc容器中这个类型的bean有多个,查找就会报错
Person person = ioc.getBean(Person.class);
//这样使用 即便ioc容器中这个类型的bean有多个,查找也不会报错
Person person = ioc.getBean("person1",Person.class);
}
复制代码
<bean id="person1" class="com.bean.Person">
<constructor-arg name="personName" value="张三"></constructor-arg>
<constructor-arg name="personAge" value="18"></constructor-arg>
<!--此处可以省略name属性,但需要按照构造器参数的顺序指定value值-->
<constructor-arg value="张三"></constructor-arg>
<constructor-arg value="18"></constructor-arg>
<!--index="0" 为参数指定索引 从0开始-->
<constructor-arg value="张三" index="0"></constructor-arg>
<constructor-arg value="18" index="1"></constructor-arg>
<!--如果有多个有参构造器 使用type指定参数类型-->
<constructor-arg value="张三" index="0"></constructor-arg>
<constructor-arg value="18" index="1" type="java.lang.Integer"></constructor-arg>
</bean>
复制代码
public void test(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
Person person = ioc.getBean("person1");
}
复制代码
名称空间:在xml中名称空间是用来防止标签重复的
<!--使用p名称空间赋值时,需先导入p名称空间-->
<bean id="person1" class="com.bean.Person" p:personName="张三" p:personAge="18">
</bean>
复制代码
//实体类
public class Person{
private String name;
private int age;
private Car car;//Car是一个实体类
private List<Book> books;//Book是一个实体类
private Map<String,Object> maps;
private Properties properties;
}
复制代码
<bean id="car" class="com.bean.Car">
<property name="carNmae" value="宝马"></property>
</bean>
<bean id="book" class="com.bean.Book">
<property name="bookNmae" value="西游记"></property>
</bean>
<bean id="person1" class="com.bean.Person">
<!--赋值为null-->
<property name="name">
<null/>
</property>
<!--ref="car" 这是一个严格的引用 person中的car跟 直接从容器中获取的car是一样的-->
<property name="car" ref="car"></property>
<!--为list类型赋值-->
<property name="books">
<list>
<!--内部bean 写id和不写id是一样的 外部获取不到-->
<bean id="book" class="com.bean.Book" p:bookName="西游记"></bean>
<ref bean="book"/>
</list>
</property>
<!--为map类型赋值-->
<bean id="maps">
<!--底层用的是LinkedHashMap-->
<map>
<!--一个entry代表一个键值对-->
<entry key="key1"value="value1"></entry>
<entry key="key2"value="value2"></entry>
<entry key="key3"value-ref="book"></entry>
<entry key="key4">
<!--内部bean无法用id获取 无论是否有id-->
<bean id="" class="com.bean.Car">
<property name="carName" value="宝马"></property>
</bean>
</entry>
</map>
</bean>
<!--为Properties类型赋值-->
<bean name="properties">
<!--properties 里面 所有的k=v都是String类型-->
<props>
<prop key="username">root</prop>
<prop key="username">123456</prop>
</props>
</bean>
</bean>
复制代码
<bean id="car01" class="cam.bean.Car">
<property name="carName" value="宝马"></property>
</bean>
<bean id="person" class="cam.bean.Person">
<property name="car" ref="car01"></property>
<property name="car.carName" value="奔驰"></property>
</bean>
复制代码
<bean id="person1" class="com.bean.Person">
<property name="perName" value="张三"></property>
<property name="perAge" value="15"></property>
<property name="perGender" value="男"></property>
</bean>
<!--parent="" : 指定当前的bean的配置信息继承于哪个bean class=""可以省略不写 -->
<bean id="person2" class="com.bean.Person" parent="person1">
<property name="perName" value="张三"></property>
</bean>
<!--abstract="true" 表示这个bean只能被继承 不可以获取-->
<bean id="person3" class="com.bean.Person" parent="person1" abstract="true">
<property name="perGender" value="男"></property>
</bean>
复制代码
<!--原来是按照配置的顺序创建bean--> <bean id="person" class="com.bean.Person"></bean> <bean id="car" class="com.bean.Car"></bean> <bean id="book" class="com.bean.Book"></bean> <!-- depends-on="car,book" 改变bean的创建顺序--> <bean id="person" class="com.bean.Person" depends-on="car,book"></bean> <bean id="car" class="com.bean.Car"></bean> <bean id="book" class="com.bean.Book"></bean> 复制代码
<bean id="book" class="com.bean.Book" scope=""></bean> 复制代码
scope="" 设置作用域 默认所有的bean都是单实例的
静态工厂:工厂本身不用创建对象,通过静态方法调用,对象 = 工厂类.工厂方法名();
public class AirPlaneStaticFactory{
//这个方法是静态方法
public static AirPlane getAirPlane(String planeName){
AirPlane airplane = new AirPlane();
airplane.setPlaneName(planeName);
return airPlane;
}
}
复制代码
<!--静态工厂(不需要创建工厂本身) 1.class指定静态工厂全类名, 2.factory-method 指定工厂方法, 3.constructor-arg 可以为方法传参 --> <bean id="airPlane" class="com.factory.AirPlaneStaticFactory" factory-method="getAirPlane"> <constructor-arg name="planeName" value="大飞机1号" ></constructor-arg> </bean> 复制代码
public void test(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
//获取到的是飞机 并不是工厂
AirPlane airplane = ioc.getBean("airPlane");
}
复制代码
**实例工厂:**工厂本身需要创建对象,
工厂类 工厂对象 = new 工厂类();
对象 =工厂对象.工厂方法名();
public class AirPlaneInstanceFactory{
//这个方法不是静态方法
public AirPlane getAirPlane(String planeName){
AirPlane airplane = new AirPlane();
airplane.setPlaneName(planeName);
return airPlane;
}
}
复制代码
<!--实例工厂(需要创建工厂本身)--> <bean id="airPlaneInstanceFactory" class="com.factory.AirPlaneInstanceFactory"> </bean> <!--factory-bean="" 指定当前对象由哪个工厂创建 factory-method=""指定工厂方法--> <bean id="airPlane" class="com.bean.AirPlane" factory-bean="airPlaneInstanceFactory" factory-method="getAirPlane"> <constructor-arg name="planeName" value="大飞机2号" ></constructor-arg> </bean> 复制代码
public void test(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
//获取到的是飞机 并不是工厂
AirPlane airplane = ioc.getBean("airPlane");
}
复制代码
public class MyFactoryBeanImpl implements FactoryBean<Book>{
//getObject:工厂方法 返回创建的对象
@Override
public Book getObject() throws Exception{
Book book = new Book();
book.setId(1);
return book;
}
//返回 创建的对象的类型
@Override
public Class<?> getObjectType(){
return Book.class;
}
//返回 是否是单例
//false : 不是单例 true: 是单例
@Override
public boolean isSingleton(){
return false;
}
}
复制代码
<!-- 注意!:无论 isSingleton()这个方法返回值是什么 ioc容器启动的时候不会创建这个实例--> <bean id="myFactoryBeanImpl" class="com.factory.MyFactoryBeanImpl"></bean> 复制代码
**注意 获取到的是book对象 **
public void test(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
//获取到的是book对象
Book book = ioc.getBean("myFactoryBeanImpl");
}
复制代码
<bean id="book" class="com.bean.Book" destory-method="" init-method="" > </bean> 复制代码
<bean id="book" class="com.bean.Book" destory-method="" init-method="" scope="protorype" > </bean> 复制代码
数据库链接池作为单实例是最好的,一个项目就一个连接池,连接池里面管理很多链接,链接是直接从链接池里面拿
可以让Spring帮我们创建连接池对象 管理连接池
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
</bean>
复制代码
jdbc.properties
#username=root jdbc.username=root jdbc.password=123456 jdbc.jdbcUrl=jdbc:mysql://localhost:3306/test jdbc.driverClass=com.mysql.jdbc.Driver 复制代码
在ApplicationContext.xml中配置时 需要引入context命名空间
<!--加载外部配置文件的 classpath: 表示引用类路径下的配置文件-->
<context:property-placeholder location="classpath:jdbc.properties" />
<!--username 是spring中的一个关键字 在这里不可以使用username-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--<property name="user" value="${username}"></property>-->
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
</bean>
复制代码
**注意!自动装配仅限于自定义类型的属性 **
<bean id="car" class="com.bean.Car">
<property name="carName" value="宝马"></property>
<property name="color" value="白色"></property>
</bean>
<!--
autowire=""
default/no:不自动装配,不自动为car属性赋值
byName:以属性名作为id去容器中找到一个组件,给他赋值,如果找不到就赋值null
byType:以属性的类型作为查找依据去容器中找到这个组件,如果容器中有多个这样的类型会报错
constructor:按照有参构造器为car赋值
1.先按照有参构造器参数类型进行装配,没有就直接为组件装配null
2.如果按照类型找到了多个bean:以参数的名作为id继续装配,找不到就null
假设有一个List<Book> books属性,容器可以把容器中所有的book封装进list
-->
<bean id="person" class="com.bean.Person" autowire="default"></bean>
复制代码
<bean id="car" class="com.bean.Person">
<property name="carName" value="宝马"></property>
</bean>
<bean id="person" class="com.bean.Person">
<property name="age" value="#{12*5}"></property>
<property name="perName" value="#{car.carName}"></property>
<property name="car" value="#{car}"></property>
<property name="email" value="#{T(java.util.UUID).randomUUID().toString()}"></property>
<property name="testName" value="#{car.getCarName()}"></property>
</bean>
复制代码
给要添加的组件上标上以上四个注解之一
告诉spring,自动扫描加了注解的组件,依赖context命名空间
<!--自动组件扫描--> <!--base-package="" 指定扫描的基础包--> <context:component-scan base-package=""></context:component-scan> 复制代码
type="annotation":按照注解进行排除-->标注了指定注解的组建不要
expression="":注解的全类名
type="assignable":按照类进行排除
expression="":类的全类名
type="aspectj":aspectj表达式(很少用)
type="custom":自定义一个TypeFilter;自己写代码决定哪些使用(很少用)
type="regex":正则表达式(很少用)
<context:component-scan base-package="">
<!--表示标注了@controller的注解不进行扫描-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!--表示com.controller.BookController这个类不进行扫描-->
<context:exclude-filter type="assignable" expression="com.controller.BookController"/>
</context:component-scan>
复制代码
type="annotation":按照注解进行排除-->标注了指定注解的组建不要
expression="":注解的全类名
type="assignable":按照类进行排除
expression="":类的全类名
type="aspectj":aspectj表达式(很少用)
type="custom":自定义一个TypeFilter;自己写代码决定哪些使用(很少用)
type="regex":正则表达式(很少用)
<context:component-scan base-package="" use-default-filters="true">
<!--表示只有标注了@controller的注解进行扫描-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!--表示只有com.controller.BookController这个类进行扫描-->
<context:include-filter type="assignable" expression="com.controller.BookController"/>
</context:component-scan>
复制代码 这里bean的id默认就是类名首字母小写
使用注解加入到容器中的组件,和使用配置加入到容器中的组件行为都是默认一样的:
public void test(){
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
Object bean = ioc.getBean("");
}
复制代码 @Repository("你想要的id名") 四个注解都是一样的
复制代码
@Scope(value="prototype") 复制代码
@Autowired为bookservice自动赋值
@Controller
public class BookServlet{
@Autowired
private BookService bookService;
}
复制代码
先 按照类型 去容器中找到对应的组件;bookService = ioc.getBean("BookService.class");
@Autowired
public void methods(@Qualifier("newbookservice")BookService bookservice){
System.out.println("")
}
复制代码
导包 导入spring-test-4.0.0
@ContextConfiguration使用这个注解来指定spring的配置文件的位置
@RunWith()指定用哪种驱动进行单元测试。默认就是junit
@RunWith(SpringJUnit4ClassRunner.class)
使用spring的单元测试模块来执行标注了@Test注解的测试方法
以前的@Test只是由JUnit执行
@ContextConfiguration(locations="classpath:spring.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringTest{
ApplicationContext ac = null;
@Autowired
BookServlet bookServlet;
}
复制代码
public abstract class BaseDao<T>{
public abstract void save();
...
}
复制代码
@Repository
public class BookDao extends BaseDao<Book>{
@Override
public void save(){
...
}
...
}
复制代码
@Repository
public class UserDao extends BaseDao<User>{
@Override
public void save(){
...
}
...
}
复制代码
@Service
public class BookService extends BaseService<Book>{
...
}
复制代码
@Service
public class UserService extends BaseService<User>{
...
}
复制代码
public class BaseService<T>{
@Autowired
private BaseDao<T> baseDao;
public void test(){
baseDao.save();
}
...
}
复制代码
@Test
public void test() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("spring.xml");
BookService bookService = ioc.getBean(BookService.class);
bookService.test();
}
复制代码