IOC:(Inversion(反转) Of Control):控制反转java
DI:(Dependency Injection)依赖注入mysql
<!--一个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");
}
复制代码
注意!web
<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中名称空间是用来防止标签重复的spring
<!--使用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>
复制代码
注意sql
<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都是单实例的数据库
静态工厂:工厂自己不用建立对象,经过静态方法调用,对象 = 工厂类.工厂方法名();express
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 工厂类();session
对象 =工厂对象.工厂方法名();
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");
}
复制代码
FactoryBean 是Spring规定的一个接口,只要是这个接口的实现类 ,spring都认为是一个工厂,Spring会自动调用工厂方法建立实例
第一步:须要写一个实现了FactoryBean接口的类
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>
复制代码
spring管理链接池引用外部配置文件
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有四个注解某个类上注解任何一个均可以讲这个组件加入到ioc容器中
使用注解将组价快速加入到容器中须要几步
给要添加的组件上标上以上四个注解之一
告诉spring,自动扫描加了注解的组件,依赖context命名空间
<!--自动组件扫描-->
<!--base-package="" 指定扫描的基础包-->
<context:component-scan base-package=""></context:component-scan>
复制代码
使用context:exclude-filter指定扫描包时不包含的类
扫描的时候能够排除一些不要的组件
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>
复制代码
使用context:include-filter指定扫描包时包含的类
指定只扫描哪些组件,
注意!须要使用 use-default-filters="false" 取消默认行为
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>
复制代码
必定要导入AOP包 支持加注解模式
这里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;
}
复制代码
@Autowired原理
先按照类型去容器中找到对应的组件;bookService = ioc.getBean("BookService.class");
注意!
可使用required=false 来解决 若是@Autowired找不到指定bean 就赋值为null
@Autowired(required=false)
@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();
}
复制代码