创建对象的三种方式
1,构造器(无参构造器,有参构造器)
public class App01 { @Test public void test01() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Book bean = context.getBean(Book.class); System.out.println(bean); }
**无参构造器
<bean class="com.offcn.bean.Book">
public Book() { System.out.println("无参构造调用了"); }
输出:
无参构造调用了
Book [bid=0, bname=null, bprice=0.0]
**有参构造器
<bean class="com.offcn.bean.Book">
<constructor-arg name="bid" value="1"></constructor-arg>
<constructor-arg name="bname" value="红楼梦"></constructor-arg>
<constructor-arg name="bprice" value="30.2"></constructor-arg>
</bean>
public Book(int bid, String bname, double bprice) {this.bid = bid; this.bname = bname; this.bprice = bprice; System.out.println("有参构造调用了");
}
输出:
有参构造调用了
Book [bid=1, bname=红楼梦, bprice=30.2]
2 静态工厂:通过类的静态方法返回的对象
public class App01 { @Test public void test01() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Book bean = context.getBean(Book.class); System.out.println(bean); } }
<bean class="com.offcn.test.StaticFactory" factory-method="getBook"></bean>
public class StaticFactory { public static Book getNewstance() { Book book = new Book(2,"水浒传",33.53); return book; } }
输出:
有参构造调用了
Book [bid=2, bname=水浒传, bprice=33.53]
3实例工厂:通过类对象的普通方法返回的对象
public class App01 { @Test public void test01() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Book bean = context.getBean(Book.class); System.out.println(bean); }
}
<bean id="getSimpleNewstance" class="com.offcn.test.SimpleFactory"></bean>
<bean factory-bean="getSimpleNewstance" factory-method="getBook"></bean>
public class SimpleFactory { public Book getBook() { Book book = new Book(3,"西游记",50); return book; } }
输出:
有参构造调用了
Book [bid=3, bname=西游记, bprice=50.0]
给对象的属性赋值的三种方式
三种数据类型: 1.基本类型和String类型 2.其他bean类型(必须是在spring配置文件中出现过的bean) 3.复杂类型(集合类型)
标签的属性
//表示给哪个参数赋值
name:指定参数的set方法名称
type:指定参数的类型
index:指定参数的索引位置,从0开始
//表示给参数具体赋什么值
value:指定基本数据类型或String类型的数据
ref:指定其他bean类型数据
1.使用构造器
涉及的标签:<constructor-arg></constructor-arg>
public class App01 { @Test public void test01() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Book bean = (Book)context.getBean("book"); System.out.println(bean); } }
<bean id="book" class="com.offcn.bean.Book">
<constructor-arg name="bid" value="1" type="java.lang.String"></constructor-arg>
<constructor-arg name="bname" value="红楼梦"></constructor-arg>
<constructor-arg name="bprice" value="30.2" index="1"></constructor-arg>
</bean>
public Book(int bid, String bname, double bprice) { super(); this.bid = bid; this.bname = bname; this.bprice = bprice; System.out.println("未更改的有参构造"); } public Book(String bid,double bprice, String bname) { super(); this.bid = Integer.valueOf(bid); this.bname = bname; this.bprice = bprice; System.out.println("更改了参数类型和索引的有参构造"); } }
输出:
更改了参数类型和索引的有参构造
Book [bid=1, bname=红楼梦, bprice=30.2]
2.使用set方法
涉及的标签:第一种:<property></property>
public class App01 { @Test public void test01() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Book bean = (Book)context.getBean("book"); System.out.println(bean); } }
<bean id="book" class="com.offcn.bean.Book">
<property name="bid" value="2"></property>
<property name="bname" value="三国演义"></property>
</bean>
public void setBid(int bid) { System.out.println("调用了setBid方法"); this.bid = bid;
}
输出:
调用了setBid方法
Book [bid=2, bname=三国演义, bprice=0.0]
第二种:p名称空间
public class App01 { @Test public void test01() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Book bean = (Book)context.getBean("book"); System.out.println(bean); } }
xmlns:p="http://www.springframework.org/schema/p"
<bean id="book" class="com.offcn.bean.Book" p:bid="3" p:bname="原来你还在那里" p:bprice="30.90"></bean>
输出:
Book [bid=3, bname=原来你还在那里, bprice=30.9]
3.使用注解
复杂属性注入
数组
列表
集合
Map
properties
@Test public void test02() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); FiexList bean = (FiexList)context.getBean("fiexlist"); // 数组类型 Object[] arr = bean.getArr(); for (Object object : arr) { System.out.println(object); } // list类型 List list = bean.getList(); System.out.println(list); // map类型 Map map = bean.getMap(); Set<Entry<Object,Object>> entrySet = map.entrySet(); for (Entry<Object, Object> entry : entrySet) { Object key = entry.getKey(); Object value= entry.getValue(); System.out.println(key+":"+value); } }
<bean id="book" class="com.offcn.bean.Book"> <constructor-arg name="bid" value="20"></constructor-arg> <constructor-arg name="bname" value="红楼梦"></constructor-arg> <constructor-arg name="bprice" value="30.2"></constructor-arg> </bean> <bean id="fiexlist" class="com.offcn.bean.FiexList"> <!-- 数组类型的属性,使用array标签给属性赋值 --> <property name="arr"> <array> <value>1</value> <ref bean="book"/> <bean class="com.offcn.bean.Book"> <property name="bname" value="三生三世"></property> </bean> </array> </property> <!-- list类型的属性,使用list标签给属性赋值 --> <property name="list"> <list> <value>2</value> <ref bean="book"/> <bean class="com.offcn.bean.Book"> <property name="bname" value="三生三世"></property> </bean> </list> </property> <!-- set属性同数组和list写法一样,使用set标签给属性赋值 --> <!-- map类型的属性,使用map标签给属性赋值 --> <property name="map"> <map> <entry key="key1" value="value1"></entry> <entry key="key2" value="book"></entry> <entry key-ref="book" value="value3"></entry> </map> </property> </bean>
数组类型和list类型输出:
[2, Book [bid=20, bname=红楼梦, bprice=30.2], Book [bid=0,
bname=三生三世, bprice=0.0]]
map类型输出:
key1:value1
key2:book
Book [bid=20, bname=红楼梦, bprice=30.2]:value3
IOC注解
1@Component用于创建bean对象的注解
几个常用的创建bean对象的其他注解
@Controller:表示该类对象时控制层【web层】的一个组件
@Service:表示该类对象是在业务逻辑层【service层】的一个组件
@Repository:表示该类对象是在持久化层【dao层】的一个组件
public class App01 { @Test public void test01(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Book book = (Book)context.getBean("book"); System.out.println(book); } }
<context:component-scan base-package="com.offcn"></context:component-scan>
//使用注解的时候,该类对象在容器的id值默认为:简类名首字母小写 //也可以通过注解的value属性值设置该类对象在容器的id @Component("book") public class Book {
输出:
Book [bid=0, bname=null, bprice=0.0]
2.给对象的属性赋值的注解
@Value给基本类型的属性赋值
@Component("book") //scope注解相当于xml配置的标签里的scope属性,设置是否为单例 @Scope public class Book { @Value("101") private int bid; @Value("一本好书") private String bname; @Value("89.9") private double bprice;
输出:
Book [bid=101, bname=一本好书, bprice=89.9]
@Autowire给引用类型的属性赋值,是spring的注解
@Test public void test01(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Book book = (Book)context.getBean("book"); System.out.println(book); }
@Component public class Author { private int age; private String name;
@Component("book") //scope注解相当于<bean scope="">标签里的scope属性,设置是否为单例 @Scope public class Book { @Value("101") private int bid; @Value("一本好书") private String bname; @Value("89.9") private double bprice; @Autowired private Author author;
输出:
Book [bid=101, bname=一本好书, bprice=89.9, author=Author [age=0, name=null]]
@Resource给引用类型的属性赋值,是jdk自带的
<bean id="at" class="com.offcn.bean.Author"></bean>
public class Book { @Value("101") private int bid; @Value("一本好书") private String bname; @Value("89.9") private double bprice; //@Autowired @Resource(name="at") private Author author;
输出:
Book [bid=101, bname=一本好书, bprice=89.9, author=Author [age=0, name=null]]
说明:
@Autowire:先根据该属性的类型去容器中找该类型的唯一bean对象,如果有唯一bean对象就将该容器中的唯一bean对象赋值给该属性,如果没有,报错,或者容器中有多个该该类型的bean对象,再根据Autowire注解标记的属性名去容器中找,看看容器中的哪个bean对象的id值和该属性名一致,如果有,就将容器中的这个对象赋值给该属性。
3.加载properties配置文件信息
@Test public void test02() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Person per = context.getBean(Person.class); System.out.println(per); }
jdbc.properties配置文件内容包含
jdbc.userName=root
<context:component-scan base-package="com.offcn"></context:component-scan>
<!-- 加载properties配置文件的 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
@Component public class Person { @Value("${jdbc.userName}") private String name; @Override public String toString() { return "Person [name=" + name + "]"; } }
输出:
Person [name=root]
Aop
为了将业务逻辑功能的关注点和这些通用化功能的关注点分离开来,就出现了Aop的技术!
通用化功能代码的实现,对应的就是所谓的切面【Aspect】
业务代码和通用功能代码分离之后,责任明确,架构就能变得高内聚低耦合
定义:全称:Aspect Oriented Programming,面向切面编程,和OOP相互促进、相互补充的关系、
是在OOP原有类代码的基础上,在不改变源代码的前提下,对原有类的功能 进行拓展。
解决:解决了软件工程中提出的关注点分离问题,让不同的部分解决不同的问题。
底层实现:cglib代理 + jdk动态代理
具体应用:声明式事务、缓存、日志处理、全局异常处理。
Aop涉及到的几个重要概念
通知【Advice】:被拓展的功能,称之为通知【本质:方法】
切面【Aspect】:通知所在的类,称之为切面【本质:类】
切入点【PointCut】:指定对谁进行拓展【本质:表达式】
连接点【JoinPoint】:通知 和 目标方法的交点,称之为:连接点
目标对象【Target】:被拓展的类对象,称之为目标对象织入【Weaving】: 将通知 应用到 目标方法的过程,称之为织入
图解Aop中涉及到的几个概念
Aop的技术实现步骤:
1.导包
2.将被扩展的类和切面类放入容器中【配置扫描包+类上加@Component】
3.Spring的配置文件中开启基于注解的切面支持,并在切面类上,加上@Aspect注解
4.在切面的通知上指定切入点表达式
具体步骤:
package com.offcn.bean; public interface Caculator { public int add(int i,int j); public int jian(int i,int j); public int cheng(int i,int j); public int div(int i,int j); }
@Component public class CaculatorImp implements Caculator { //方法签名:包名+类名+方法名+参数列表 @Override public int add(int i, int j) { int result = i+j; System.out.println("目标方法执行了"); return result; }
<context:component-scan base-package="com.offcn"></context:component-scan>
<!-- 开启基于注解的切面支持 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
@Component @Aspect public class LogAspect { //切入点表达式 @Before(value="execution(public int com.offcn.bean.CaculatorImp.add(int, int))") public void beforeLog() { System.out.println("在目标方法执行之前执行"); } @After(value="execution(public int com.offcn.bean.CaculatorImp.add(int, int))") public void afterLog() { System.out.println("在目标方法执行之后执行"); } }
public class App01 { @Test public void test01() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Caculator bean = context.getBean(Caculator.class); bean.add(3, 4); }
输出:
在目标方法执行之前执行
目标方法执行了
在目标方法执行之后执行