1、Hello 对象由谁创建?
hello对象由Spring创建。
2、Hello对象的属性怎么设置?
hello对象的属性由Spring容器设置。
XML架子:为了以后方便使用
<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
http://www.springframework.org/schema/beans/spring-beans.xsd">
...
beans>
3、这个过程就叫控制反转:
控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的.
反转:程序本身不创建对象,而变成被动的接收对象. 依赖注入:就是利用set方法来进行注入的.
4、IOC是一种编程思想,由主动的编程变成被动的接收.
5、可以通过new ClassPathXmlApplicationContext去浏览一下底层源码.
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
1.使用无参构造创建对象,默认;
2.假设我们使用有参构造创建对象;
1)通过下标创建
2)通过类型创建(不建议使用)
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
bean>
3)通过参数名设置
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg name="years" value="7500000"/>
<constructor-arg name="ultimateAnswer" value="42"/>
bean>
3、总结:在配置文件加载的时候,容器中管理的对象就已经初始化了!
<bean id="user" class="com.hubz.pojo.User" >
<constructor-arg type="java.lang.String" value="鸡蛋"/>
bean>
<alias name="user" alias="userNew"/>
<bean id="user" class="com.hubz.pojo.User" name="u1 u2,u3;u4" >
<constructor-arg type="java.lang.String" value="鸡蛋"/>
bean>
<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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="beans.xml"/>
<import resource="beans2.xml"/>
beans>
使用的时候直接使用总的就可以了,别名以及其他也会合并
public class UserServiceImpl implents UserService{
private UserDao userDao;
@Autowire
public UserServiceImpl(UserDao userDao){
this.userDao = userDao;
}
}
public class UserServiceImpl implents UserService{
private UserDao userDao;
@Autowire
public serUserDao(UserDao userDao){
this.userDao = userDao;
}
}
【环境搭建】
复杂类型
Student.java
import java.util.*;
public class Student {
private String name;
private Address address;
private String[] strings;
private List<String> list;
private Map<String,String> map;
private Set<String> set;
private String wife;
private Properties info;
}
Address.java
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
beans.xml
<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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="address" class="com.hubz.pojo.Address">
<property name="address" value="上海" />
bean>
<bean id="student" class="com.hubz.pojo.Student">
<property name="name" value="东方"/>
<property name="address" ref="address"/>
<property name="books" >
<array>
<value>三国演义value>
<value>水浒传value>
<value>西游记value>
<value>红楼梦value>
array>
property>
<property name="list">
<list>
<value>看书value>
<value>写作value>
list>
property>
<property name="map">
<map>
<entry key="身份证" value="47864512165"/>
<entry key="考号" value="325453156452"/>
map>
property>
<property name="set">
<set>
<value>hahahvalue>
<value>Testvalue>
set>
property>
<property name="wife">
<null/>
property>
<property name="info">
<props>
<prop key="driver">Driverprop>
<prop key="url">小明prop>
<prop key="root">郝仁prop>
<prop key="password">123456prop>
props>
property>
bean>
beans>
真实测试对象
测试类
import com.hubz.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new
ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.getName());
}
}
p命名空间:添加
xmlns:p="http://www.springframework.org/schema/p"
c命名空间:添加
xmlns:c="http://www.springframework.org/schema/c"
使用
User.java
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public User() {}
...
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
userbeans.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.hubz.pojo.User" p:name="东方" p:age="20"/>
<bean id="user2" class="com.hubz.pojo.User" c:name="狂神" c:age="18"/>
beans>
MyTest.java
import com.hubz.pojo.Student;
import com.hubz.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
@Test
public void test2(){
ApplicationContext context = new
ClassPathXmlApplicationContext("userbeans.xml");
User user = context.getBean("user",User.class);
System.out.println(user.toString());
User user2 = context.getBean("user2",User.class);
System.out.println(user2.toString());
}
}
注意点:p命名空间和c命名空间不能直接使用,需要导入xml约束
写法:(Spring 默认机制)
<bean id="user2" class="com.hubz.pojo.User"
c:name="狂神" c:age="18"
scope="singleton"
/>
写法:(每次从容器中get时都会产生一个新对象)
<bean id="user2" class="com.hubz.pojo.User"
c:name="狂神" c:age="18"
scope="prototype"
/>
其余的request、session、application这些只能在web开发中用到
Spring有三种装配的方式
环境搭建:一个人有两个宠物
byName
<bean id="cat" class="com.hubz.pojo.Cat"/>
<bean id="dog" class="com.hubz.pojo.Dog"/>
<bean id="people" class="com.hubz.pojo.People" autowire="byName">
<property name="name" value="张亮"/>
bean>
byType
<bean id="cat" class="com.hubz.pojo.Cat"/>
<bean class="com.hubz.pojo.Dog"/>
<bean id="people" class="com.hubz.pojo.People" autowire="byType">
<property name="name" value="张亮"/>
bean>
小结
jdk1.5支持的注解,Spring2.5就支持注解了!
The introduction of annotation-based configurations raised the question of whether this approach is ‘better’ than XML.
使用注解须知:
导入约束:
xmlns:context="http://www.springframework.org/schema/context"
配置注解的支持:
<context:annotation-config/>
<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.xsd">
<context:annotation-config/>
beans>
public class People {
@Autowired
private Dog dog;
private Cat cat;
private String name;
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public Cat getCat() {
return cat;
}
@Autowired
public void setCat(Cat cat) {
this.cat = cat;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "People{" +
"dog=" + dog +
", cat=" + cat +
", name='" + name + '\'' +
'}';
}
}
科普:
@Nullable //字段标记了这个注解,说明这个字段可以为null
public class People {
@Autowired
private Dog dog;
@Autowired
//在有多个配置的情况下,不使用这个会发生找不到的情况
//作用就是唯一指定
@Qualifier(value="cat111")
private Cat cat;
private String name;
//参数可以为空,而不报错
public People(@Nullable Cat cat) {
this.cat = cat;
}
}
如果@Autowired自动装配环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候,我们可以使用@Qualifier(value=“xxx”)去配置@Autowired的使用,指定一个唯一的Bean对象注入。
<bean id="dog111" class="com.hubz.pojo.Dog"/>
<bean id="dog11" class="com.hubz.pojo.Dog"/>
public class People {
@Resource
private Dog dog;
/**
* @Resource:
* 先找和变量名字一样的,有则注入;
* 没有则按照类型查找:
* 如果只有一个同类型,注入;
* 如果有多个同类型,报错;
* 都没找到:
* 报错
*
* 可以指定查找:指定查找也只能有一个,不知为何?
*/
@Resource(name = "cat1")
private Cat cat;
}
@Resource和@Autowired的区别
在Spring4之后,要使用注解开发,必须要保证aop的包导入了
使用注解需要注解的支持
<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.xsd">
<context:component-scan base-package="com.hubz.pojo"/>
<context:annotation-config/>
beans>
该组件放在类上,说明这个类被Spring管理了,就是bean
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
// 等价于
// @Component :组件
@Component
public class User {
// public String name = "东方";
// 相当于
// 简单的使用Value,复杂的建议使用配置文件
// @Value("dongdong") //可以放在这,也可以放在set上
public String name;
@Value("dongdong")
public void setName(String name) {
this.name = name;
}
}
并且让扫描器扫描全局
<context:component-scan base-package="com.hubz"/>
这四个注解的功能都是一样的,都代表会将某个类注册到Spring中,装配Bean
@Component
@Scope("prototype") //一般不用,这个注解都少见
public class User {
public String name;
}
xml与注解
xml与注解最佳实践
xml用来管理bean
注解只负责完成属性的注入
我们在使用的过程中只需要注意一个问题:必须让注解生效,就需要开启注解的支持
<context:component-scan base-package="com.hubz.pojo"/>
<context:annotation-config/>
我们现在完全不使用xml,全权交给Java来做!
JavaConfig是Spring的一个子项目,在Spring 4 之后,他成为了一个核心功能!
@Component
public class User {
@Value("dass")
public String name;
public void setName(String name)
{
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
//这个注解也是将这个类被Spring托管,注册到容器中,因为他本来就是一个@Component
// @Configuration 代表这是一个配置类,就和我们之前看的beans.xml一样
@Configuration
@ComponentScan("hubz.pojo")
@Import(Config2.class) //引入其他配置类,引成一个类,和beans.xml中的import功能一样
public class HbConfig {
/**
* 注册一个bean,就相当于我们之前写的一个bean标签;
* 这个方法的名字,就相当于bean标签中的id属性
* 这个方法的返回值,就相当于bean标签中的class属性
*/
@Bean
public User getUser(){
return new User(); //就是返回要注入到bean的对象
}
}
测试类
import hubz.config.HbConfig;
import hubz.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyTest {
public static void main(String[] args) {
//如果完全使用了配置类方式去做,我们就只能通过 AnnotationConfig 上下文来获取容器,通过配置类的cLass对象加载!
ApplicationContext context = new AnnotationConfigApplicationContext(HbConfig.class);
User user = context.getBean("getUser",User.class);
System.out.println(user.name);
}
}
这种纯Java的配置方式,在SpringBoot中随处可见
为什么要学代理模式?因为这是SpringAOP的底层!【SpringAOP和SpringMVC】
代理模式的分类;
静态代理
动态代理
角色分析
代理模式的好处:
代理模式的缺点:
代码步骤:
面向对象七大原则:看一看
需要了解两个类:Proxy:代理;InvocationHandler:调用处理程序
动态代理的好处:
提供声明式事务:允许用户自定义切面
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5中类型的Advice:
通知类型 | 连接点 | 实现接口 |
---|---|---|
前置通知 | 方法前 | org.springframework.aop.MethodBeforeAdvice |
后置通知 | 方法后 | org.springframework.aop.AfterReturningAdvice |
环绕通知 | 方法前后 | org.aoplliance.intercept.MethodInterceptor |
异常抛出通知 | 方法抛出异常 | org.springframework.aop.ThrowsAdvice |
引介通知 | 类中增加新的方法属性 | org.springframework.aop.IntroductionInterceptor |
即AOP在不改变原有代码的情况下,去增加新的功能。
【重点】使用AOP织入,需要导入一个依赖包
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.5version>
dependency>
方式一:使用Spring的API接口【主要SpringAPI接口实现】
方式二:自定义类【主要是切面定义】
方式三:使用注解实现
步骤:
导入相关JAR包
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.2version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.1.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.2.1.RELEASEversion>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.8.13version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>2.0.3version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.8version>
dependency>
编写配置文件
测试
<configuration>
<typeAliases>
<package name="com.hubz.pojo"/>
typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/shangxuan?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
environments>
<mappers>
<package name="com.hubz.mapper"/>
mappers>
configuration>
<mapper namespace="com.hubz.mapper.UserMapper">
...
mapper>
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
com.hubz.mapper.UserMapper.selectUser
去class文件中查看mapper.xml文件是否输出进去,发现没有【静态资源过滤问题】
<build>
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.xmlinclude>
includes>
<filtering>truefiltering>
resource>
resources>
build>
<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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/shangxuan?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/hubz/mapper/*.xml"/>
bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"/>
bean>
beans>
然后在applicationContext.xml添加如下配置就可以了
<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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="spring-dao.xml"/>
<bean id="userMapper" class="com.hubz.mapper.UserMapperImpl">
<property name="sqlSessionTemplate" ref="sqlSession"/>
bean>
beans>
思考:
为什么需要事务?
hubz/mapper/*.xml"/>
```
然后在applicationContext.xml添加如下配置就可以了
<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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="spring-dao.xml"/>
<bean id="userMapper" class="com.hubz.mapper.UserMapperImpl">
<property name="sqlSessionTemplate" ref="sqlSession"/>
bean>
beans>
思考:
为什么需要事务?