Spring
IOC理论
1.场景:
传统开发:三层架构之间要组合调用,通过new调用对象实现
userDao 接口
UserDaoimpl 实现类
UserService 业务接口
UserSerciveImpl 业务实现类
问题:service组合时UserDao userdao = new MysqlImp()
new OrcaleImp()//多态所引起的,会需要调用处写死多个实现类对象,用户的不同需求会影响原来的代码
解决:
1.用set实现动态注入需要的实现类对象,以便调后续的方法,将主动new对象权释放
spring的本质是ioc,控制反转:即我们主动new对象这一过程被第三方给接管,由第三方实现。
配置步骤
1.引入maven依赖
2.编写配置文件(官网有)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="services.xml"/>
<import resource="resources/messageSource.xml"/>
<import resource="/resources/themeSource.xml"/>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here --> <property name="accountDao" ref="accountDao"/>
<property name="itemDao" ref="itemDao"/>
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
每一个bean标签接管一个对象的创建,其中id是唯一标识通过它来get容器中的对象,class是标识对象的全限定类名
property:对象中要注入的属性 ref使用容器中创建好的对象
import:引入其他的配置文件(mybatis.xml)
3使用:
ApplicationContext context = new ClassPathXmlApplicationContext("配置文件名.xml");
PetStoreService service = context.getBean("petStore", PetStoreService.class);
基于XML
1.ioc创建对象方式
1.默认走的无参构造
2.使用构造器有参构造注入
Constructor Argument Resolution:
方式一:
public class ThingOne {
public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {
// ...
}
}
<bean id="beanOne" class="x.y.ThingOne">
<constructor-arg ref="beanTwo"/>
<constructor-arg ref="beanThree"/>
</bean>
方式二:type matching
public class ExampleBean {
// Number of years to calculate the Ultimate Answer
private final int years;
// The Answer to Life, the Universe, and Everything
private final String ultimateAnswer;
public ExampleBean(int years, String ultimateAnswer) {
this.years = years;
this.ultimateAnswer = ultimateAnswer;
}
}
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean>
方式三:index参数下标
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg index="0" value="7500000"/>
<constructor-arg index="1" value="42"/>
</bean>
方式四:通过名称
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg name="years" value="7500000"/>
<constructor-arg name="ultimateAnswer" value="42"/>
</bean>
3.复杂类型注入
bean | ref | idref | list | set | map | props | value | null
4.c p 命名空间
相当于语法糖:省略property和constructor
xmlns:p="http://www.springframework.org/schema/p"
<bean name="john-modern"
class="com.example.Person"
p:name="John Doe"
p:spouse-ref="jane"/>
xmlns:c="http://www.springframework.org/schema/c"
<bean id="beanOne" class="x.y.ThingOne" c:thingTwo-ref="beanTwo"
c:thingThree-ref="beanThree" c:email="something@somewhere.com"/>
5.bean的作用域可以设置
6.隐式自动装配
with the autowire attribute of the <bean/> element.加上 autowire属性
基于注解
1.开启注解和扫描包(加上value不然出bug)
2在类上 @Conponent
@Repository
@Service
@control 类即被spring接管id默认为首字母小写
- @Required:应用于set方法
The @Required annotation applies to bean property setter methods, as in the following example:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Required
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
- @Autowired:应用于set函数和属性上
You can apply the @Autowired annotation to constructors, as the following example shows:
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
前提要注入的bean在ioc中已经存在默认通过name装配
@Primary
:优先默认装配
@Configuration
public class MovieConfiguration {
@Bean
@Primary
public MovieCatalog firstMovieCatalog() { ... }
@Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
// ...
}
优先装配到加了@Primary
- @Qualifier:配合 @Autowired指定xml中的哪一个bean装配给谁最好指定value
public class MovieRecommender {
@Autowired
@Qualifier("main")
private MovieCatalog movieCatalog;
// ...
}
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(@Qualifier("main") MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
<bean class="example.SimpleMovieCatalog">
<qualifier value="main"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier value="action"/>
<!-- inject any dependencies required by this bean -->
</bean>
- @Resource(name=“xx”)
- @vlaue注入属性值
基于注解的配置
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
等价于
<beans>
<bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>
- 使用
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}
开启包扫描
@Configuration
@ComponentScan(basePackages = "com.acme")
public class AppConfig {
// ...
}
注册其他的配置文件
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class, OtherConfig.class);
ctx.register(AdditionalConfig.class);
ctx.refresh();
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}
@Bean(“name”)在方法上方法名即为id名
@Configuration
public class AppConfig {
@Bean
public TransferServiceImpl transferService() {
return new TransferServiceImpl();
}
}
等价于
<beans>
<bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>
使用@Import(ConfigA.class)
@Configuration
public class ConfigA {
@Bean
public A a() {
return new A();
}
}
@Configuration
@Import(ConfigA.class)
public class ConfigB {
@Bean
public B b() {
return new B();
}
}
配置类引入xml
<beans>
<!-- picks up and registers AppConfig as a bean definition -->
<context:component-scan base-package="com.acme"/>
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
</beans>
@Configuration
@ImportResource("classpath:/com/acme/properties-config.xml")
public class AppConfig {
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource(url, username, password);
}
}