DI:依赖注入
环境准备,即写一个spring测试,见工程
构造器注入
即使用构造器来给Bean的对象的属性赋值
MyBean
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MyBean {
private Long id;
private String name;
private OtherBean otherBean;
}
OtherBean
public class OtherBean {
}
SpringTest-Context.xml
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--<constructor-arg 构造器注入 普通属性注入 index/name/type:下标/名称/类型, value:赋值 -->
<!-- <bean id="myBean" class="cn.ming._01constructor.MyBean">-->
<!-- 1.构造器注入,普通属性注入,index:下标,value:赋值 -->
<!-- <constructor-arg index="0" value="1"/>-->
<!-- <constructor-arg index="1" value="时光鸡11"/>-->
<!-- 2.构造器注入,普通属性注入,name:名称,value:赋值 -->
<!-- <constructor-arg name="id" value="1"/>-->
<!-- <constructor-arg name="name" value="时光鸡12"/>-->
<!-- 3.构造器注入,普通属性注入,type:类型,value:赋值。如果有重复类型就不能用这种,一般不用这种 -->
<!-- <constructor-arg type="java.lang.Long" value="1"/>-->
<!-- <constructor-arg type="java.lang.String" value="时光鸡13"/>-->
<!-- 0.这是前面学过的setter方法注入,普通属性注入,name:属性名称 - set方法后面的属性,value:赋值 -->
<!-- <property name="id" value="123"></property>-->
<!-- <property name="name" value="王天霸"></property>-->
<!-- </bean>-->
<!--引用属性注入-->
<!-- <bean id="otherBean" class="cn.itsource._01constructor.OtherBean"/>-->
<!-- <bean id="myBean" class="cn.itsource._01constructor.MyBean">-->
<!-- <constructor-arg index="0" value="1"/>-->
<!-- <constructor-arg index="1" value="时光鸡20"/>-->
<!--引用外部bean-->
<!-- <constructor-arg index="2" ref="otherBean"/>-->
<!-- </bean>-->
<!--引用属性注入-->
<bean id="myBean" class="cn.itsource._01constructor.MyBean">
<constructor-arg index="0" value="1"/>
<constructor-arg index="1" value="时光鸡21"/>
<!--引用内部bean -->
<constructor-arg index="2">
<bean class="cn.itsource._01constructor.OtherBean"/>
</constructor-arg>
</bean>
</beans>
SpringTest
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration//回到当前类的包下 查找当前类名-Context.xml的配置文件
public class SpringTest {
@Autowired
MyBean myBean;
@Test
public void testSpring(){
System.out.println(myBean);
}
}
setter方法注入
即用setter方法给bean对象的属性赋值
MyBean
@Data
public class MyBean {
// 1.简单属性
private Long id;
private String name;
private Boolean sex;
private BigDecimal salary;
// 2.普通集合属性
private List<String> stringList;
private Set<String> stringSet;
// 3.引用集合属性
private List<OtherBean> otherBeanList;
private Set<OtherBean> otherBeanSet;
// 4.数组
private String[] arrays1;
private String[] arrays2;
// 5.properties
private Properties props1;
private Properties props2;
@Override
public String toString() {
System.out.println("stringList======"+stringList);
System.out.println("stringSet======"+stringSet);
System.out.println("otherBeanList======"+otherBeanList);
System.out.println("otherBeanSet======"+otherBeanSet);
System.out.println("arrays1======"+ Arrays.asList(arrays1));
System.out.println("arrays2======"+ Arrays.asList(arrays2));
System.out.println("props1======"+ props1);
System.out.println("props2======"+ props2);
return "MyBean{" +
"id=" + id +
", name='" + name + '\'' +
", sex=" + sex +
", salary=" + salary +
'}';
}
}
OtherBean
public class OtherBean {
}
SpringTest-Context.xml
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="otherBean" class="cn.itsource._02property.OtherBean"/>
<bean id="myBean" class="cn.itsource._02property.MyBean">
<property name="id" value="1"/>
<property name="name" value="张三"/>
<property name="sex" value="true"/>
<property name="salary" value="10000000000"/>
<property name="stringList">
<list>
<value>小红帽</value>
<value>小红帽</value>
<value>大红帽</value>
<value>老红帽</value>
</list>
</property>
<property name="stringSet">
<set>
<value>小红帽</value>
<value>小红帽</value>
<value>大红帽</value>
<value>老红帽</value>
</set>
</property>
<property name="otherBeanList">
<list>
<ref bean="otherBean"/>
<ref bean="otherBean"/>
<bean class="cn.itsource._02property.OtherBean"/>
<bean class="cn.itsource._02property.OtherBean"/>
</list>
</property>
<property name="otherBeanSet">
<set>
<ref bean="otherBean"/>
<ref bean="otherBean"/>
<bean class="cn.itsource._02property.OtherBean"/>
<bean class="cn.itsource._02property.OtherBean"/>
</set>
</property>
<!--完整写法-->
<property name="arrays1">
<array>
<value>时,光鸡</value>
<value>光鸡</value>
<value>鸡</value>
</array>
</property>
<!--简写 如果元素内有逗号会解析为分隔符,不推荐用这种-->
<property name="arrays2" value="时光鸡,光鸡,鸡"/>
<!--完整写法 支持中文-->
<property name="props1">
<props>
<prop key="driver">com.mysql.jdbc.Driver</prop>
<prop key="url">jdbc:mysql:///哈哈</prop>
</props>
</property>
<!--简写 不支持中文-->
<property name="props2">
<value>
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///哈哈
</value>
</property>
</bean>
</beans>
SpringTest
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration//回到当前类的包下 查找当前类名-Context.xml的配置文件
public class SpringTest {
@Autowired
MyBean myBean;
@Test
public void testSpring(){
System.out.println(myBean);
}
}
AOP
概念
事务管理:比如可以抽取try catch的重复代码
日志监控:比如业务逻辑前后打印关于当前订单数量的日志,了解业务做了什么
性能监控:比如业务前后打印时间,相减可查看业务跑完所需时间
代理模式引出
用aop实现扩展功能,
aop用代理模式实现,但是代理模式里的扩展功能还是需要我们自己写,
静态代理:相当于一个中介只代理一个固定的房东的房源,基本不用
动态代理:默认没有,使用的时候动态生成
AOP:以上大方向
SpringAOP:AOP的spring实现方式,用动态代理方式实现。它的实现方式又有两种:jdk,CGLIB,spring自动选择用其中哪种方式,代理类自动生成也不用管,有接口的时候默认使用jdk,没有的时候用cglib(第三方jar包),现在一般service都有接口
AOP实现方式
xml方式实现
1.编写TxManager用来提供业务逻辑外的扩展功能 - 如事务管理
/*我们自己的扩展功能*/
public class TxManager {
public void open (){
System.out.println("开启事务");
}
public void commit (){
System.out.println("提交事务");
}
public void rollback(Throwable e){
e.printStackTrace();//处理异常
System.out.println("回滚事务");
}
public void close(){
System.out.println("关闭事务");
}
public void around(ProceedingJoinPoint point){
try {
open();
point.proceed();//执行真正的业务
commit();
} catch (Throwable e) {
e.printStackTrace();
rollback(e);
} finally {
close();
}
}
}
2.准备xmlAOP环境,在Spring配置文件中引入头支持以支持aop标签
SpringTest-Context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
3.配置的三要素
何时,如在业务的执行前、后、catch
何地,指的是在哪一个方法
做什么,执行我们自定义扩展业务类的方法
面向切面编程,面向扩展功能编程
其他
spring通过动态代理实现aop,配置aop后只能注入接口,通过接口找到被引用的代理类,Spring容器中就只有代理类没有实现类,
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration//回到当前类的包下 查找当前类名-Context.xml的配置文件
public class SpringTest {
@Autowired
IUserService userService;
@Test
public void testUser(){
System.out.println(userService.getClass());
}
}
SpringTest-Context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="userService" class="cn.itsource._03aopxml.service.impl.UserServiceImpl"/>
<bean id="departmentService" class="cn.itsource._03aopxml.service.impl.DepartmentServiceImpl"/>
<!--将扩展功能交给Spring容器管理,方便AOP使用-->
<bean id="txManager" class="cn.itsource._03aopxml.TxManager"/>
<!--SpringAOP的核心配置-->
<aop:config>
<!--配置切点 配置何地 ==在哪一个方法执行
expression:表达式 通过表达式,我们找在哪一个方法执行
第一个*:任意返回值
I*Service:所有以I开头 Service结尾的类(里面的所有方法都加上事物)
第三个*:任意方法
save(..):任意参数
-->
<!--execution(* cn.itsource._03aopxml.service.impl.UserServiceImpl.save(..))
execution(* cn.itsource._03aopxml.service.impl.UserServiceImpl.*(..))-->
<aop:pointcut id="txPoint" expression="execution(* cn.itsource._03aopxml.service.I*Service.*(..))"/>
<!--配置切面 -->
<aop:aspect ref="txManager">
<!--配置前置通知 配置何时做什么-->
<!--<aop:before method="open" pointcut-ref="txPoint"/>-->
<!--配置后置通知-->
<!--<aop:after-returning method="commit" pointcut-ref="txPoint"/>-->
<!--配置异常通知-->
<!--<aop:after-throwing method="rollback" pointcut-ref="txPoint" throwing="e"/>-->
<!--配置最终通知-->
<!--<aop:after method="close" pointcut-ref="txPoint"/>-->
<!--配置环绕通知 环绕通知一行顶上面四行-->
<aop:around method="around" pointcut-ref="txPoint"/>
</aop:aspect>
</aop:config>
</beans>
测试
详细见工程代码文章来源:https://www.toymoban.com/news/detail-656545.html
注解方式实现
A 引入容器扫描头 Spring AOP
SpringTest-Context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启Spring注解扫描-->
<context:component-scan base-package="cn.itsource._04aopanno"/>
<!--开启SpringAOP 注解扫描-->
<aop:aspectj-autoproxy/>
</beans>
后面的几步,都是在TxManager中完成
B 将扩展业务交给容器管理 @Component
C 申明pointcut,@Pointcut,需要提供一个空方法
D 配置各种通知
只用@Around环绕通知,其他四种通知不能确定执行顺序,
/*我们自己的扩展功能*/
@Component //组件 把当前类交给Spring容器管理
@Aspect //== <aop:aspect ref="txManager"> 配置切面
public class TxManager {
//配置切点 == <aop:pointcut id="txPoint"
@Pointcut("execution(* cn.itsource._04aopanno.service.I*Service.*(..))")
public void txPoint(){
/*这个方法指明在业务类中的每个方法*/
}
/*配置前置通知*/
/*@Before("txPoint()")*/
public void open (){
System.out.println("开启事物");
}
/*@AfterReturning("txPoint()")*/
public void commit (){
System.out.println("提交事物");
}
/*@AfterThrowing(value = "txPoint()", throwing = "e")*/
public void rollback(Throwable e){
e.printStackTrace();//处理异常
System.out.println("回滚事务");
}
/*@After("txPoint()")*/
public void close(){
System.out.println("关闭事物");
}
@Around("txPoint()")
public void around(ProceedingJoinPoint point){
try {
open();
point.proceed();//执行真正的业务
commit();
} catch (Throwable e) {
e.printStackTrace();
rollback(e);
} finally {
close();
}
}
}
测试
详细见工程代码
Spring创建Bean
直接创建
以上创建方式都属于直接创建,如文章来源地址https://www.toymoban.com/news/detail-656545.html
<bean id="userService" class="cn.ming._03aopxml.service.impl.UserServiceImpl"/>
工厂类的静态方法创建
Car
public class Car {
}
CarFactory
public class CarFactory {
public static Car createCar(){
return new Car();
}
}
SpringTest-Context.xml
<bean id="car" class="cn.itsource._05create._02.CarFactory" factory-method="createCar"/>
SpringTest
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration//回到当前类的包下 查找当前类名-Context.xml的配置文件
public class SpringTest {
@Autowired
Car car;
@Test
public void testUser() {
System.out.println(car);
}
}
工厂类的非静态方法创建
Car
public class Car {
}
CarFactory
public class CarFactory {
public Car createCar(){
return new Car();
}
}
SpringTest-Context.xml
<bean id="carFactroy" class="cn.itsource._05create._03.CarFactory"/>
<bean id="car" factory-bean="carFactroy" factory-method="createCar"/>
SpringTest
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration//回到当前类的包下 查找当前类名-Context.xml的配置文件
public class SpringTest {
@Autowired
Car car;
@Test
public void testUser() {
System.out.println(car);
}
}
FactoryBean方式创建
Car
public class Car {
}
CarFactoryBean
public class CarFactoryBean implements FactoryBean<Car> {
// 设置返回的bean
@Override
public Car getObject() throws Exception {
return new Car();
}
// 设置返回值类型
@Override
public Class<?> getObjectType() {
return Car.class;
}
// 设置是否单例
@Override
public boolean isSingleton() {
return true;
}
}
SpringTest-Context.xml
<!--ctrl + alt + l
Spring中,扫描到你当前类是FactoryBean的类,他会调用getObject(),将方法的返回值作为对象管理起来
通过getObjectType()的返回值确定类型 -->
<bean id="car" class="cn.itsource._05create._04.CarFactoryBean"/>
SpringTest
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration//回到当前类的包下 查找当前类名-Context.xml的配置文件
public class SpringTest {
@Autowired
Car car;
@Autowired
Car car2;
@Test
public void testCar(){
System.out.println(car);
System.out.println(car2);
}
}
到了这里,关于B057-spring增强 依赖注入 AOP 代理模式 创建Bean的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!