maven:
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<version>5.0.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>5.0.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.0.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-context-supportartifactId>
<version>5.0.0.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-expressionartifactId>
<version>5.0.0.RELEASEversion>
dependency>
创建ioc.xml文件
文件模板:
<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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
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>
beans>
程序入口
public class test01 {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("bean-ioc.xml");
HelloController helloController = ac.getBean("HelloController", HelloController.class);
HelloService helloService = ac.getBean("HelloService", HelloService.class);
}
}
开启注解扫描:
<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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
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 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<context:component-scan base-package="ioc_01">context:component-scan>
beans>
标记要进入容器的对象:
@Component//Component标识把当前对象加入到容器中,且id就是首字母小写
public class HelloController {
@Autowired
private HelloService helloService;//AutoWired,标识用类型找到匹配的对象注入到当前对象中
public void dealRequest(String message){
helloService.sayMessage(message);
}
public HelloService getHelloService() {
return helloService;
}
public void setHelloService(HelloService helloService) {
this.helloService = helloService;
}
}
@Component
public class HelloService {
private String username;
private String password;
public HelloService(){
this.username="GodSchool";
this.password="GodSchool";
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void sayHelloWolrd(){
System.out.println("HellowWolrd"+this.username+this.password);
}
public void sayMessage(String message){
System.out.println(message);
}
}
测试:
public class test01 {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("bean-ioc.xml");
HelloController helloController = ac.getBean("helloController", HelloController.class);
HelloService helloService = ac.getBean("helloController", HelloService.class);
}
}
好了下面,我们将提出一个新的名词:bean,我们将归由ioc所管理的对象叫做bean,意味着这个对象我们利用某种方式(注解或xml)将他已经加入到容器中了;
@Bean注解:
@Configuration
public class BeanAnnotation {
@Bean //【方法名---bean的Id】
public UserController UserController(){
return new UserController();
}
@Bean("CartController")//【value---bean的Id】
public UserController CartController(){
return new UserController();
}
@Bean//【有参,以参数名从容器中获取】
public Color color(Car car){
Color color = new Color();
color.setCar(car);
return color;
}
@Improt注解(单个导入):
添加配置类:
@Configuration
@Import({
HelloController.class,HelloService.class,HelloMapper.class})
public class BeanImportConfigruation {
}
取消几个对象的注解:
public class HelloController {
@Autowired
private HelloService helloService;//这是属性名
public void dealRequest(String message){
helloService.sayMessage(message);
}
public HelloService getHelloService() {
return helloService;
}
public void setHelloService(HelloService helloService) {
this.helloService = helloService;
}
}
public class HelloMapper {
}
public class HelloService {
……
}
测试:
public class test01 {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("bean-ioc.xml");
HelloController helloController = ac.getBean(HelloController.class);
HelloService helloService = ac.getBean(HelloService.class);
HelloMapper helloMapper = ac.getBean(HelloMapper.class);
}
}
Ps:注意这种方式只能用类型匹配到对象然后取出来
@Improt注解(选择器批量导入):
/**
* @如果你想要创造的实例有复杂的选择逻辑可以用这种批量的导入方式
* 1、importingClassMetadata:当前配置类的所有注解信息
* 2、String[]:返回创建对象的全类名,可以按照某种方式生成或者写死
*/
@Configuration
@Import(BeanImportConfigruation.MyImportSelector.class)
public class BeanImportConfigruation {
public static class MyImportSelector implements ImportSelector {
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{
"ioc_01.HelloController","ioc_01.HelloService","ioc_01.HelloMapper"};
}
}
}
FactoryBean接口:
/**
* 如果你要创建的某个单实例
* 可能有复杂的创建规则可以选择工厂Bean的方式帮你实习
*/
@Configuration
public class MyFactoryBean implements FactoryBean<HelloController> {
public HelloController getObject() throws Exception {
//返回什么实例
return new HelloController();
}
public Class<?> getObjectType() {
//返回什么类型
return HelloController.class;
}
public boolean isSingleton() {
//是否单实例
return true;
}
}
【1 排除扫描法】
/**
* @利用注解配置扫包的规则
* value:注定包名
* excludeFilters:排除我们不想要创建的类型,type是利用注解方式排除
* type = FilterType.ANNOTATION, 【注解】
* type = FilterType.ASSIGNABLE_TYPE, 【类】
* type = FilterType.CUSTOM 【自定义】
*/
@Configuration
@ComponentScan(value = "ioc_01",excludeFilters = {
@ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
})
public class BeanConfiguration {
}
【2 包含扫描法】
@Configuration
@ComponentScan(value = "ioc_01",useDefaultFilters = false,
includeFilters = {
@ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
})
public class BeanConfiguration {
}
【3 自定义扫描法】
(1)建立自定义注解
public @interface MyIocAnno {
}
(2)建立自定义扫描规则
@Configuration
@ComponentScan(value = "ioc_01",useDefaultFilters = false,
includeFilters = {
@ComponentScan.Filter(
type = FilterType.CUSTOM,
classes = {
BeanConfiguration.MyFilter.class}
)
})
public class BeanConfiguration {
public static class MyFilter implements TypeFilter{
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
/**
* annotationMetadata:每个被扫描类的注解信息
* resource:每个被扫描的文件信息
* classMetadata:每个被扫描的类的对象信息
* 依据这些信息的描述,我们来创建对象,我下面用自定义注解作为举例 如果存在我们的注解就决定创建
* 这些被扫描的范围是value指定的所有下级包,ioc_01下
*/
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
Resource resource = metadataReader.getResource();
ClassMetadata classMetadata = metadataReader.getClassMetadata();
boolean ifExistMyIocAnno = annotationMetadata.hasAnnotation("ioc_01.MyIocAnno");
return ifExistMyIocAnno;
}
}
}
【修饰】
@Primary//自动装配的时候,首选bean;
@Lazy//懒加载模式
@Scope("prototype")
* prototype:多实例的:始终懒加载!
* singleton:单实例的(默认值):默认非懒加载
* request:同一次请求创建一个实例
* session:同一个session创建一个实例
【例子】
@Primary
@Scope("prototype")
@Bean("person")
@DependsOn决定事先创建
public Person person(){
System.out.println("给容器中添加Person....");
return new Person("张三", 25);
}
利用注解方式注入容器中的其他对象,有两者方式;一个是类型,一个按照名称;
按照类型(不存在类型冲突)
@Controller
public class HelloController {
@Autowired
private HelloService helloService;
public void dealRequest(String message){
helloService.sayMessage(message);
}
public HelloService getHelloService() {
return helloService;
}
public void setHelloService(HelloService helloService) {
this.helloService = helloService;
}
}
Ps:required=false,找不到的时候就不会抛出异常;可以设置,匹配多个的时候,会按照属性名二次匹配,再找不到会抛出异常;
按照类型(存在类型冲突,比如一个接口有多个实现类的对象都在容器中,就会冲突)
@Controller
public class HelloController {
@Qualifier("userServiceImpl")
@Autowired
private HelloService helloService;
public void dealRequest(String message){
helloService.sayMessage(message);
}
public HelloService getHelloService() {
return helloService;
}
public void setHelloService(HelloService helloService) {
this.helloService = helloService;
}
}
@Service("helloServiceImpl")
public class HelloService {
}
Ps:可以指定value按照类型或者名称查找,没有value按照类名查找;
复合型
@Controller
public class HelloController {
@Resource(name="userServiceImpl")
private HelloService helloService;
}
@Controller
public class HelloController {
@Resource(type=HelloService.class)
private HelloService helloService;
}
在这里插入代码片
有时候,我们希望们的对象创建的时候,它的属性由某个配置文件指定更方面维护,比如jdbc,那么就得用这个特性;
加载外部配置文件:
@PropertySource(value = {
"classpath:myApp.properties"})//相对于resource目录去加载环境变量
public class NavController {
@Value("$(App.App-name)")
private String AppName;
}
加载SpringBoot的配置文件——指定加载(以后看):
@Component
public class NavController {
@Value("$(App.App-name)")//不支持松散大写语法因此value值中写-来区分
private String AppName;
}
Ps:支持SpEL表达式-@Value("#{person.hegith/person.width}")
加载SpringBoot的配置文件——前缀自动对应(以后看):
@Component
@ConfigurationProperties(prefix = "person")
public class TbNav {
private Integer nid;
private String ntext;
private Integer pid;
}
基本运用:
1、算数运算符:+,-,*,/,%,^。加号还可以用作字符串连接。
2、比较运算符:<,>,==,<=,>=,It,gt,eg,le,ge
3、逻辑运算度:and,or,not,if-else运算符
Ps:除了XML外,spel用于注解取值也是可以的
${key名称} : 用户获取全局参数中指定key的值@Value("#{'${jdbc.url}'}")
#{SPEL表达式}: 访问当前容器中bean对象,并可以做代码操作;
<property name="suffix" value="#{sequenceGenerator2.suffix}"/>
<property name="suffix" value="#{sequenceGenerator2.toString().toUpperCase()}"/>
<property name="initValue" value="#{T(java.lang.Math).PI}">property>通过T()调用一个类的静态方法
<property name="initValue" value="#{new Double(3.1415926)}">property>
【修饰】
@Primary//自动装配的时候,首选bean;
@Lazy//懒加载模式
@Scope("prototype")
* prototype:多实例的:始终懒加载!
* singleton:单实例的(默认值):默认非懒加载
* request:同一次请求创建一个实例
* session:同一个session创建一个实例
【例子】
@Primary
@Scope("prototype")
@Bean("person")
@DependsOn决定事先创建
public Person person(){
System.out.println("给容器中添加Person....");
return new Person("张三", 25);
}
Spring对组件进行构造时,首先会利用递归的形式先将最内层的组件放在容器中,然后依次将自己的组件地址,注入给外层组件;为了解耦的实现,我们一般注入的接口,而不是直接的实现类;接口多个实现类冲突,需要修饰指定唯一;
@Controller
public class HelloController {
public HelloController(){
System.out.println("构造器");
}
@PostConstruct
public void init(){
System.out.println("构造器后置处理");
}
@PreDestroy
public void destory(){
System.out.println("销毁前置处理");
}
}
构造器
构造器后置处理
销毁前置处理
关于生命周期,还有一条BeanPostPorcesser系列,很多框架利用这个特性完成了完美的与Spring框架整合的特性,我们在后续章节陆续推出
后续Spring专题:
SpringIOC——内部工具全套
SpringIOC——核心源码剖析